Damage Reasons API
Module Overview
The DamageReasonsModule provides a CRUD catalog for business-specific reasons why inventory items were damaged. These reasons are referenced by damage_report_line records when creating damage reports.
| Controller | Base Path | Description |
|---|---|---|
| DamageReasonsController | /damage-reasons | CRUD for damage/loss reason catalog entries |
Authentication
All endpoints require Firebase authentication:
- Header:
Authorization: Bearer <firebase-id-token> - Cookie: Alternatively, send the token via the
flowpos-id-tokencookie
Architecture
damage-reasons/
├── damage-reasons.module.ts # NestJS module (DI wiring)
├── domain/
│ └── damage-reasons-repository.domain.ts # Port interface + injection token
├── application/
│ └── damage-reasons.service.ts # Business logic (framework-agnostic params)
├── infrastructure/
│ └── damage-reasons.repository.ts # Kysely implementation
└── interfaces/
├── damage-reasons.controller.ts # HTTP routes (Swagger-documented)
├── dtos/
│ ├── create-damage-reason.dto.ts
│ └── update-damage-reason.dto.ts
└── query/
└── paginate-damage-reasons.query.ts
Key design decisions:
- Repository injected via
DAMAGE_REASONS_REPOSITORYsymbol token (dependency inversion) - Service accepts plain parameter objects — no DTO imports from the interfaces layer
- Hard delete on reasons; FK on
damage_report_line.damageReasonIdusesonDelete("set null")
Endpoints
1. Create Damage Reason
POST /damage-reasons
Body:
| Field | Type | Required | Description |
|---|---|---|---|
businessId | UUID | Yes | UUID of the owning business |
name | string | Yes | Human-readable name (e.g. "Breakage") |
description | string | No | Longer explanation of when this reason applies |
createdBy | UUID | No | UUID of the creating user |
Response: 201 — The created damage reason object.
2. List Damage Reasons
GET /damage-reasons
Query parameters:
| Param | Type | Default | Description |
|---|---|---|---|
businessId | UUID | — | Required. Filter by business |
q | string | — | Search by name (case-insensitive) |
page | number | 1 | Page number |
limit | number | 50 | Items per page |
includeInactive | boolean | false | Include inactive reasons |
Response: 200
{
"currentPage": 1,
"pages": 3,
"results": [
{
"id": "uuid",
"businessId": "uuid",
"name": "Breakage",
"description": "Items damaged during handling",
"isActive": true,
"createdAt": "2026-03-01T00:00:00.000Z",
"createdBy": "uuid",
"updatedAt": null,
"updatedBy": null
}
]
}
3. Get Damage Reason by ID
GET /damage-reasons/:id
Response: 200 — Single damage reason object. 404 if not found.
4. Update Damage Reason
PATCH /damage-reasons/:id
Body (all optional):
| Field | Type | Description |
|---|---|---|
name | string | Updated name |
description | string | Updated description |
isActive | boolean | Toggle active/inactive status |
updatedBy | UUID | UUID of the user making the change |
Response: 200 — The updated damage reason object.
5. Delete Damage Reason
DELETE /damage-reasons/:id
Response: 200
{
"message": "DamageReason <id> deleted."
}
This is a hard delete. Existing damage_report_line rows referencing this reason will have damage_reason_id set to null.
Bruno Collection
API requests are available in:
api-client/flowpos/collections/damage-reasons/
Environment variables used: BASE_URL, ID_TOKEN, businessId, userId, damageReasonId.
Database Schema
CREATE TABLE damage_reason (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
business_id UUID NOT NULL REFERENCES business(id),
name VARCHAR NOT NULL,
description TEXT,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID,
updated_at TIMESTAMPTZ,
updated_by UUID
);
The damage_report_line table references damage_reason(id) with ON DELETE SET NULL.