# Customers API Router

# Customers API Router

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [src/http/protected-router.ts](src/http/protected-router.ts)
- [src/lib/bulk/bulk-action-runner.ts](src/lib/bulk/bulk-action-runner.ts)
- [src/modules/customers/audit-transformer.ts](src/modules/customers/audit-transformer.ts)
- [src/modules/customers/dto.ts](src/modules/customers/dto.ts)
- [src/modules/customers/router.ts](src/modules/customers/router.ts)

</details>



The Customers API Router defines the RESTful interface for managing customer entities. It serves as the orchestration layer between HTTP requests and the `CustomersDal`, enforcing security via RBAC, validating data via Zod schemas, and providing standardized responses for complex operations like bulk actions and streaming exports.

## Overview and Security

The router is constructed using `makeProtectedRouter` [src/modules/customers/router.ts:39](), which implements a "secure-first" policy. Every endpoint must explicitly declare a permission via `rbacHandler` [src/modules/auth/rbac.middleware.js:31](); otherwise, the router automatically injects a `defaultDenyHandler` that returns a `403 Forbidden` with the code `ROUTE_PERMISSION_NOT_DECLARED` [src/http/protected-router.ts:38-57]().

### Request Flow Architecture

The following diagram illustrates the flow from an incoming request through the security and validation layers to the Data Access Layer (DAL).

**Customer Request Pipeline**
```mermaid
graph TD
    subgraph "Express Router Layer"
        Req["Incoming HTTP Request"] --> PR["makeProtectedRouter (Express)"]
        PR --> RBAC["rbacHandler(Permission)"]
        RBAC --> VAL["validateBody / validateQuery (Zod)"]
    end

    subgraph "Customer Module Logic"
        VAL --> AH["asyncHandler"]
        AH --> Router["customersRouter Implementation"]
        Router --> DAL["CustomersDal"]
        Router --> Audit["AuditService"]
    end

    subgraph "Data Layer"
        DAL --> Pool["PostgreSQL Pool"]
        Audit --> Pool
    end

    RBAC -- "Unauthorized" --> 403["403 Forbidden"]
    VAL -- "Invalid Data" --> 400["400 Bad Request"]
```
**Sources:** [src/modules/customers/router.ts:38-48](), [src/http/protected-router.ts:87-106](), [src/modules/auth/rbac.middleware.js:31]().

---

## Metadata and Listing

### Entity Metadata
The `/meta` endpoint provides frontend consumers with the configuration necessary to render customer tables and forms dynamically.
- **Endpoint:** `GET /api/v1/entities/customer/meta`
- **Permissions:** `CUSTOMERS_READ_ALL` or `CUSTOMERS_READ_SINGLE` [src/modules/customers/router.ts:54-56]()
- **Returns:** Column definitions (`CUSTOMER_LIST_COLUMNS`), default sorting, and row action visibility [src/modules/customers/router.ts:58-79]().

### Paginated List
Retrieves a list of customers with support for complex filtering, searching, and soft-delete visibility.
- **Endpoint:** `GET /api/v1/entities/customer/list`
- **Permissions:** `CUSTOMERS_READ_ALL` [src/modules/customers/router.ts:84]()
- **Validation:** Uses `CustomerListQuerySchema` [src/modules/customers/dto.ts:72-83]().
- **Logic:**
    - Extracts `search`, `filters`, `sort_key`, and `page` parameters.
    - Maps `deleted_records` (EXCLUDED, ONLY, INCLUDED) to the DAL query [src/modules/customers/router.ts:87-127]().
    - Implements a standardized error wrapper for database failures [src/modules/customers/router.ts:130-147]().

---

## CRUD Operations

### Single Record Management
| Method | Endpoint | Permission | Description |
| :--- | :--- | :--- | :--- |
| `GET` | `/api/v1/entities/customer/:uuid` | `CUSTOMERS_READ_SINGLE` | Fetches a single record by UUID [src/modules/customers/router.ts:258](). |
| `POST` | `/api/v1/entities/customer` | `CUSTOMERS_CREATE` | Creates a new customer record [src/modules/customers/router.ts:279](). |
| `PATCH` | `/api/v1/entities/customer/:uuid` | `CUSTOMERS_UPDATE` | Updates specific fields of a record [src/modules/customers/router.ts:303](). |
| `DELETE` | `/api/v1/entities/customer/:uuid` | `CUSTOMERS_DELETE` | Soft-deletes a record [src/modules/customers/router.ts:333](). |
| `POST` | `/api/v1/entities/customer/:uuid/restore` | `CUSTOMERS_RESTORE` | Restores a soft-deleted record [src/modules/customers/router.ts:355](). |

**Data Integrity:** The `CustomerCreateBodySchema` enforces that `onboarding_at` and `onboarding_time_zone` are either both present or both absent [src/modules/customers/dto.ts:115-140]().

---

## Bulk Actions and Duplication

Bulk operations use the `runBulkAction` helper [src/lib/bulk/bulk-action-runner.ts:78](), which provides uniform RFC 7807 partial-failure semantics. If some records fail (e.g., due to foreign key constraints), the API returns a `422 Unprocessable Entity` containing lists of successful and failed UUIDs [src/lib/bulk/bulk-action-runner.ts:116-127]().

### Bulk Endpoints
- **Bulk Delete:** `POST /api/v1/entities/customer/bulk-delete` [src/modules/customers/router.ts:377]().
- **Bulk Restore:** `POST /api/v1/entities/customer/bulk-restore` [src/modules/customers/router.ts:401]().
- **Bulk Duplicate:** `POST /api/v1/entities/customer/duplicate` [src/modules/customers/router.ts:425]().
    - Unlike delete/restore, duplication is handled directly by `getDal().duplicateCustomers` to manage unique constraint logic (e.g., appending "- copy" to codes) [src/modules/customers/router.ts:431]().

**Sources:** [src/lib/bulk/bulk-action-runner.ts:1-32](), [src/modules/customers/router.ts:377-440]().

---

## Export and Audit Trail

### Streaming Export
The export endpoint streams data directly from the database to the client to minimize memory footprint.
- **Endpoint:** `GET /api/v1/entities/customer/export`
- **Permissions:** `CUSTOMERS_EXPORT` [src/modules/customers/router.ts:153]()
- **Formats:** `xlsx`, `csv`, `html` [src/modules/customers/dto.ts:218]().
- **Implementation:** Calls `getDal().streamAllCustomers` and pipes the result into `exportDataWithTemplateToStream` [src/modules/customers/router.ts:181-224]().

### Audit Trail Retrieval
Retrieves the history of changes for a specific customer, including who made the change and what fields were modified (delta).
- **Endpoint:** `GET /api/v1/entities/customer/:uuid/audit`
- **Permissions:** `CUSTOMERS_READ_AUDIT` [src/modules/customers/router.ts:233]()
- **Transformation:** The raw database audit logs are processed by `transformAuditEntries` [src/modules/customers/audit-transformer.ts:118](). This converts technical field keys into human-readable labels and formats values (e.g., dates) according to the `it-IT` locale [src/modules/customers/audit-transformer.ts:26-76]().

**Audit Data Mapping**
```mermaid
classDiagram
    class CustomerAuditEntry {
        +uuid entity_uuid
        +string action
        +Record delta
        +number version
    }
    class AuditEntryTransformed {
        +string title
        +string[] description
        +string who
        +string changed_at
    }
    class AuditTransformer {
        +formatFieldChange(key, change)
        +formatAction(action)
        +transformAuditEntry(entry)
    }

    CustomerAuditEntry --> AuditTransformer : Input
    AuditTransformer --> AuditEntryTransformed : Output
```
**Sources:** [src/modules/customers/router.ts:231-256](), [src/modules/customers/audit-transformer.ts:78-129](), [src/modules/customers/dto.ts:191-209]().

---
