Repair Issue Notes Module
Overview
The repair-issue-notes module tracks items sent for repair as part of a customer return. When a customer return is approved with a "REPAIR" condition, a repair issue note is created to follow the item through the repair lifecycle until it is returned to the customer.
Domain Concepts
Status Lifecycle
IN_REPAIR → REPAIRED → RETURNED
| Status | Description |
|---|---|
IN_REPAIR | Item is currently being repaired |
REPAIRED | Repair completed, awaiting return to customer |
RETURNED | Repaired item returned to customer |
Key Entities
- Repair Issue Note — the document tracking a repair, linked to a customer return
- Detail — JSON object containing the line items being repaired (product, quantity, price, taxes)
- Cost Detail — optional JSON snapshot of item costs at time of creation
Relationships
| Entity | Relationship |
|---|---|
customer_return | Originating return (FK: customerReturnId) |
customer | Customer who owns the item (FK: customerId) |
business | Multi-tenant scope (FK: businessId) |
location | Store handling the repair (FK: locationId) |
currency | Transaction currency (FK: currencyId) |
Architecture
repair-issue-notes/
├── repair-issue-notes.module.ts
├── domain/
│ └── repair-issue-notes-repository.domain.ts # Port interface, sortable keys, enum re-exports
├── application/
│ ├── repair-issue-notes.service.ts # Use cases + event emission
│ └── events/
│ └── on-update-repair-issue-note.event.ts # Update event payload
├── infrastructure/
│ └── repair-issue-notes.repository.ts # Kysely adapter
└── interfaces/
├── repair-issue-notes.controller.ts # HTTP endpoints (Swagger-documented)
├── dtos/
│ ├── create-repair-issue-note.dto.ts
│ └── update-repair-issue-note.dto.ts
└── query/
└── paginate-repair-issue-notes.query.ts
Layer Dependencies
- Domain — framework-agnostic: repository interface, sortable keys, enum re-exports
- Application — orchestrates: existence checks, event emission after updates
- Infrastructure — Kysely queries implementing
IRepairIssueNotesRepository - Interfaces — thin controller mapping HTTP to service calls
Cross-Module Integration
| Module | Relationship |
|---|---|
| Customer Returns | Originating document; repair note references customerReturnId |
| Inventories | InventoryReturnHandler listens for repairIssueNote.update events to process inventory adjustments |
API Endpoints
| Method | Path | Description |
|---|---|---|
POST | /repair-issue-notes | Create a repair issue note |
GET | /repair-issue-notes | List with pagination, search, and sorting |
GET | /repair-issue-notes/:id | Get a single repair issue note |
PATCH | /repair-issue-notes/:id | Update (status transitions) |
DELETE | /repair-issue-notes/:id | Delete a repair issue note |
Query Parameters (GET list)
| Parameter | Type | Description |
|---|---|---|
size | number | Page size (0 = no limit) |
page | number | Page number (1-based) |
orderBy | string | Sort field: status, taxId, taxName, taxAddress, locationName |
order | string | Sort direction: asc or desc |
search | string | Full-text search across sortable fields |
Example: Create Repair Issue Note
POST /repair-issue-notes
{
"businessId": "550e8400-e29b-41d4-a716-446655440000",
"status": "IN_REPAIR",
"createdBy": "550e8400-e29b-41d4-a716-446655440001",
"issueDate": "2026-03-26",
"customerId": "550e8400-e29b-41d4-a716-446655440002",
"taxId": "17195594",
"taxName": "LUIS RANGEL",
"taxAddress": "CIUDAD",
"locationId": "550e8400-e29b-41d4-a716-446655440003",
"locationName": "Main Store",
"totalAmount": 24.00,
"exchangeRate": 7.90,
"totalBaseAmount": 21.43,
"currencyId": "550e8400-e29b-41d4-a716-446655440004",
"detail": {
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440010",
"productId": "550e8400-e29b-41d4-a716-446655440005",
"productName": "COCA COLA",
"goodOrService": "B",
"unitOfMeasure": "UNI",
"quantity": 1,
"unitPrice": 12.00,
"total": 12.00
}
]
},
"customerReturnId": "550e8400-e29b-41d4-a716-446655440006"
}
Example: Update Status to REPAIRED
PATCH /repair-issue-notes/:id
{
"status": "REPAIRED",
"updatedBy": "550e8400-e29b-41d4-a716-446655440001"
}
Event-Driven Integration
Emitted Events
| Event | Trigger | Payload |
|---|---|---|
repairIssueNote.update | Any PATCH update | { previousRepairIssueNoteRecord, updatedRepairIssueNoteRecord } |
Consumers
| Handler | Module | Action |
|---|---|---|
InventoryReturnHandler.handleOnUpdateRepairIssueNoteEvent() | Inventories | Processes inventory adjustments based on status transitions |
Design Decisions
- Event-driven side effects — Status changes emit events rather than directly calling inventory logic, keeping modules decoupled.
- Denormalized tax/location fields —
taxId,taxName,taxAddress,locationNameare stored on the document to preserve the snapshot at creation time, even if the source records change later. - JSON detail column — Line items are stored as a JSON blob rather than normalized child rows, matching the pattern used by customer returns and other document modules.