# Debt Reminder Policies API Documentation

## Overview

The Debt Reminder Policies API allows you to manage automated debt reminder policies for residents. Each policy defines when and how debt reminders should be sent to residents based on various targeting criteria.

**Base URL**: `/api/v1/debt-reminder-policies`

**Authentication**: All endpoints require a valid Bearer token in the Authorization header.

**Role Requirements**: Admin access required for all endpoints.

---

## Table of Contents

- [Data Models](#data-models)
- [GET /api/v1/debt-reminder-policies](#get-apiv1debt-reminder-policies)
- [GET /api/v1/debt-reminder-policies/{id}](#get-apiv1debt-reminder-policiesid)
- [POST /api/v1/debt-reminder-policies](#post-apiv1debt-reminder-policies)
- [PUT /api/v1/debt-reminder-policies/{id}](#put-apiv1debt-reminder-policiesid)
- [DELETE /api/v1/debt-reminder-policies/{id}](#delete-apiv1debt-reminder-policiesid)

---

## Data Models

### Debt Reminder Policy

| Field | Type | Description |
|-------|------|-------------|
| id | string (UUID) | Unique identifier |
| name | string | Policy name |
| reminder_type | enum | `BEFORE_DUE`, `AFTER_DUE`, `ON_DUE_DATE` |
| days_offset | number | Days offset (negative for before due, positive for after due, 0 for on due date) |
| send_time | string | Time to send reminder in HH:MM format (24h) |
| channels | string[] | Array of channels: `APP_PUSH`, `SMS`, `EMAIL`, `ZALO` |
| status | enum | `ACTIVE`, `INACTIVE` |
| created_by | string (UUID) | User ID who created the policy |
| updated_by | string (UUID) | User ID who last updated the policy |
| created_at | string (ISO 8601) | Creation timestamp |
| updated_at | string (ISO 8601) | Last update timestamp |

### Policy Target

| Field | Type | Description |
|-------|------|-------------|
| id | string (UUID) | Unique identifier |
| policy_id | string (UUID) | Parent policy ID |
| target_type | enum | `ALL`, `BUILDING`, `APARTMENT`, `ROOM`, `RESIDENT` |
| target_id | string (UUID) | Target entity ID (null if target_type is ALL) |
| target_details | object | Detailed information about the target (see below) |
| created_by | string (UUID) | User ID who created the target |
| updated_by | string (UUID) | User ID who last updated the target |
| created_at | string (ISO 8601) | Creation timestamp |
| updated_at | string (ISO 8601) | Last update timestamp |

### Target Details Structure

The `target_details` field contains additional information about the target based on its type:

**BUILDING**:
```json
{
  "name": "Building A",
  "code": "BLD-A"
}
```

**APARTMENT**:
```json
{
  "name": "Apartment 101",
  "code": "APT-101",
  "floor": 1
}
```

**ROOM**:
```json
{
  "name": "Room 1",
  "code": "RM-1",
  "floor": 1
}
```

**RESIDENT**:
```json
{
  "full_name": "John Doe",
  "phone": "+84123456789",
  "email": "john@example.com",
  "id_card": "123456789012"
}
```

**ALL**: `null`

---

## GET /api/v1/debt-reminder-policies

Retrieve a paginated list of debt reminder policies.

### Query Parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| page | number | No | 1 | Page number |
| pageSize | number | No | 10 | Number of items per page (max 100) |
| sortField | string | No | created_at | Field to sort by |
| sortOrder | string | No | DESC | Sort order: `asc` or `desc` |
| filters | string | No | - | Filter string (see below) |

### Filter Syntax

Use the `sequelize-api-paginate` filter syntax. Examples:

```javascript
// Filter by status
filters: "status==ACTIVE"

// Filter by reminder type
filters: "reminder_type==BEFORE_DUE"

// Multiple filters
filters: "status==ACTIVE,reminder_type==BEFORE_DUE"
```

### Request Example

```bash
GET /api/v1/debt-reminder-policies?page=1&pageSize=20&sortField=created_at&sortOrder=DESC&filters=status==ACTIVE
```

### Response Example

```json
{
  "success": true,
  "data": {
    "count": 10,
    "rows": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "Nhắc nợ 7 ngày trước hạn",
        "reminder_type": "BEFORE_DUE",
        "days_offset": -7,
        "send_time": "08:00",
        "channels": ["APP_PUSH", "SMS"],
        "status": "ACTIVE",
        "created_by": "user-id-123",
        "updated_by": "user-id-123",
        "created_at": "2026-06-01T10:00:00Z",
        "updated_at": "2026-06-01T10:00:00Z"
      }
    ],
    "page": 1,
    "pageSize": 20
  }
}
```

---

## GET /api/v1/debt-reminder-policies/{id}

Retrieve a single debt reminder policy by ID with full target details.

### Path Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| id | string (UUID) | Yes | Policy ID |

### Request Example

```bash
GET /api/v1/debt-reminder-policies/550e8400-e29b-41d4-a716-446655440000
```

### Response Example

```json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Nhắc nợ 7 ngày trước hạn - Building A",
    "reminder_type": "BEFORE_DUE",
    "days_offset": -7,
    "send_time": "08:00",
    "channels": ["APP_PUSH", "SMS"],
    "status": "ACTIVE",
    "created_by": "user-id-123",
    "updated_by": "user-id-123",
    "targets": [
      {
        "id": "660e8400-e29b-41d4-a716-446655440001",
        "policy_id": "550e8400-e29b-41d4-a716-446655440000",
        "target_type": "BUILDING",
        "target_id": "c414cce9-d7f7-4b29-a78e-aa9336556559",
        "target_details": {
          "name": "Building A",
          "code": "BLD-A"
        },
        "created_by": "user-id-123",
        "updated_by": "user-id-123",
        "created_at": "2026-06-01T10:00:00Z",
        "updated_at": "2026-06-01T10:00:00Z"
      },
      {
        "id": "660e8400-e29b-41d4-a716-446655440002",
        "policy_id": "550e8400-e29b-41d4-a716-446655440000",
        "target_type": "APARTMENT",
        "target_id": "0627b9cb-efd2-452a-88b6-b552c90e6d49",
        "target_details": {
          "name": "Apartment 101",
          "code": "APT-101",
          "floor": 1
        },
        "created_by": "user-id-123",
        "updated_by": "user-id-123",
        "created_at": "2026-06-01T10:00:00Z",
        "updated_at": "2026-06-01T10:00:00Z"
      },
      {
        "id": "660e8400-e29b-41d4-a716-446655440003",
        "policy_id": "550e8400-e29b-41d4-a716-446655440000",
        "target_type": "ALL",
        "target_id": null,
        "target_details": null,
        "created_by": "user-id-123",
        "updated_by": "user-id-123",
        "created_at": "2026-06-01T10:00:00Z",
        "updated_at": "2026-06-01T10:00:00Z"
      }
    ],
    "created_at": "2026-06-01T10:00:00Z",
    "updated_at": "2026-06-01T10:00:00Z"
  }
}
```

---

## POST /api/v1/debt-reminder-policies

Create a new debt reminder policy.

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | Yes | Policy name (1-255 characters) |
| reminderType | enum | Yes | `BEFORE_DUE`, `AFTER_DUE`, `ON_DUE_DATE` |
| daysOffset | number | Yes | Days offset from due date |
| sendTime | string | Yes | Time in HH:MM format (24h) |
| channels | string[] | Yes | Array of channels (min 1): `APP_PUSH`, `SMS`, `EMAIL`, `ZALO` |
| status | enum | No | `ACTIVE`, `INACTIVE` (default: ACTIVE) |
| targets | array | Yes | Array of target objects (min 1) |

### Target Object

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| targetType | enum | Yes | `ALL`, `BUILDING`, `APARTMENT`, `ROOM`, `RESIDENT` |
| targetId | string (UUID) | Conditional | Required if targetType is not `ALL` |

### Validation Rules

- If `targetType` is `ALL`, `targetId` must be null or omitted
- If `targetType` is not `ALL`, `targetId` is required
- `sendTime` must match regex `^([0-1]\d|2[0-3]):([0-5]\d)$`

### Request Example

```bash
POST /api/v1/debt-reminder-policies
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
  "name": "Nhắc nợ 7 ngày trước hạn - Building A",
  "reminderType": "BEFORE_DUE",
  "daysOffset": -7,
  "sendTime": "08:00",
  "channels": ["APP_PUSH", "SMS"],
  "status": "ACTIVE",
  "targets": [
    {
      "targetType": "BUILDING",
      "targetId": "c414cce9-d7f7-4b29-a78e-aa9336556559"
    }
  ]
}
```

### Response Example

```json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Nhắc nợ 7 ngày trước hạn - Building A",
    "reminder_type": "BEFORE_DUE",
    "days_offset": -7,
    "send_time": "08:00",
    "channels": ["APP_PUSH", "SMS"],
    "status": "ACTIVE",
    "created_by": "user-id-123",
    "updated_by": "user-id-123",
    "targets": [
      {
        "id": "660e8400-e29b-41d4-a716-446655440001",
        "policy_id": "550e8400-e29b-41d4-a716-446655440000",
        "target_type": "BUILDING",
        "target_id": "c414cce9-d7f7-4b29-a78e-aa9336556559",
        "target_details": {
          "name": "Building A",
          "code": "BLD-A"
        },
        "created_by": "user-id-123",
        "updated_by": "user-id-123",
        "created_at": "2026-06-01T10:00:00Z",
        "updated_at": "2026-06-01T10:00:00Z"
      }
    ],
    "created_at": "2026-06-01T10:00:00Z",
    "updated_at": "2026-06-01T10:00:00Z"
  }
}
```

---

## PUT /api/v1/debt-reminder-policies/{id}

Update an existing debt reminder policy.

### Path Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| id | string (UUID) | Yes | Policy ID |

### Request Body

All fields are optional. Only provided fields will be updated.

| Field | Type | Description |
|-------|------|-------------|
| name | string | Policy name (1-255 characters) |
| reminderType | enum | `BEFORE_DUE`, `AFTER_DUE`, `ON_DUE_DATE` |
| daysOffset | number | Days offset from due date |
| sendTime | string | Time in HH:MM format (24h) |
| channels | string[] | Array of channels: `APP_PUSH`, `SMS`, `EMAIL`, `ZALO` |
| status | enum | `ACTIVE`, `INACTIVE` |
| targets | array | Array of target objects (replaces existing targets) |

**Note**: If `targets` is provided, all existing targets for this policy will be deleted and replaced with the new targets.

### Request Example

```bash
PUT /api/v1/debt-reminder-policies/550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
  "name": "Nhắc nợ 7 ngày trước hạn - Updated",
  "status": "INACTIVE",
  "targets": [
    {
      "targetType": "APARTMENT",
      "targetId": "0627b9cb-efd2-452a-88b6-b552c90e6d49"
    }
  ]
}
```

### Response Example

```json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Nhắc nợ 7 ngày trước hạn - Updated",
    "reminder_type": "BEFORE_DUE",
    "days_offset": -7,
    "send_time": "08:00",
    "channels": ["APP_PUSH", "SMS"],
    "status": "INACTIVE",
    "created_by": "user-id-123",
    "updated_by": "user-id-456",
    "targets": [
      {
        "id": "660e8400-e29b-41d4-a716-446655440004",
        "policy_id": "550e8400-e29b-41d4-a716-446655440000",
        "target_type": "APARTMENT",
        "target_id": "0627b9cb-efd2-452a-88b6-b552c90e6d49",
        "target_details": {
          "name": "Apartment 101",
          "code": "APT-101",
          "floor": 1
        },
        "created_by": "user-id-456",
        "updated_by": "user-id-456",
        "created_at": "2026-06-01T11:00:00Z",
        "updated_at": "2026-06-01T11:00:00Z"
      }
    ],
    "created_at": "2026-06-01T10:00:00Z",
    "updated_at": "2026-06-01T11:00:00Z"
  }
}
```

---

## DELETE /api/v1/debt-reminder-policies/{id}

Delete a debt reminder policy (hard delete).

### Path Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| id | string (UUID) | Yes | Policy ID |

**Note**: This is a hard delete. All associated targets will also be deleted.

### Request Example

```bash
DELETE /api/v1/debt-reminder-policies/550e8400-e29b-41d4-a716-446655440000
Authorization: Bearer YOUR_TOKEN
```

### Response Example

```json
{
  "success": true,
  "data": null
}
```

---

## Common Use Cases

### Example 1: Create a policy for all residents

```json
{
  "name": "Nhắc nợ 7 ngày trước hạn - Tất cả",
  "reminderType": "BEFORE_DUE",
  "daysOffset": -7,
  "sendTime": "08:00",
  "channels": ["APP_PUSH", "SMS"],
  "targets": [
    { "targetType": "ALL" }
  ]
}
```

### Example 2: Create a policy for specific buildings

```json
{
  "name": "Nhắc nợ 3 ngày sau hạn - Building A, B",
  "reminderType": "AFTER_DUE",
  "daysOffset": 3,
  "sendTime": "09:00",
  "channels": ["APP_PUSH", "SMS", "EMAIL"],
  "targets": [
    { "targetType": "BUILDING", "targetId": "c414cce9-d7f7-4b29-a78e-aa9336556559" },
    { "targetType": "BUILDING", "targetId": "c747e73d-168d-4103-976f-4a1acb3c23ce" }
  ]
}
```

### Example 3: Create a policy for specific apartments

```json
{
  "name": "Nhắc nợ ngay khi quá hạn - Apartments",
  "reminderType": "AFTER_DUE",
  "daysOffset": 0,
  "sendTime": "08:00",
  "channels": ["APP_PUSH", "SMS", "EMAIL", "ZALO"],
  "targets": [
    { "targetType": "APARTMENT", "targetId": "0627b9cb-efd2-452a-88b6-b552c90e6d49" },
    { "targetType": "APARTMENT", "targetId": "310e6a64-d3d4-4d5f-b8c8-3d455abcb3dd" }
  ]
}
```

### Example 4: Create a policy for specific residents

```json
{
  "name": "Nhắc nợ 5 ngày trước hạn - Residents",
  "reminderType": "BEFORE_DUE",
  "daysOffset": -5,
  "sendTime": "07:30",
  "channels": ["APP_PUSH", "SMS"],
  "targets": [
    { "targetType": "RESIDENT", "targetId": "0da44740-8986-441e-9c79-3b83f6a8dbee" },
    { "targetType": "RESIDENT", "targetId": "a91f183b-b65d-490f-9a1e-3b853cc36243" }
  ]
}
```

### Example 5: Mixed targeting (building + apartment + residents)

```json
{
  "name": "Nhắc nợ 3 ngày trước hạn - Mixed",
  "reminderType": "BEFORE_DUE",
  "daysOffset": -3,
  "sendTime": "08:30",
  "channels": ["APP_PUSH", "SMS", "EMAIL"],
  "targets": [
    { "targetType": "BUILDING", "targetId": "c414cce9-d7f7-4b29-a78e-aa9336556559" },
    { "targetType": "APARTMENT", "targetId": "0627b9cb-efd2-452a-88b6-b552c90e6d49" },
    { "targetType": "RESIDENT", "targetId": "0da44740-8986-441e-9c79-3b83f6a8dbee" }
  ]
}
```

---

## Error Handling

All endpoints follow the standard error response format:

```json
{
  "success": false,
  "error": {
    "message": "Error description",
    "code": "ERROR_CODE"
  }
}
```

### Common Error Codes

| Code | Description |
|------|-------------|
| NOT_FOUND | Resource not found |
| UNAUTHORIZED | Invalid or missing authentication token |
| FORBIDDEN | User does not have required permissions |
| VALIDATION_ERROR | Request validation failed |
| INTERNAL_SERVER_ERROR | Server error |

---

## Technical Notes

1. **Transaction Safety**: Create and Update operations use database transactions to ensure data consistency between policies and targets.

2. **Hard Delete**: DELETE operation permanently removes the policy and all associated targets. There is no soft delete for policies.

3. **Target Replacement**: When updating targets, all existing targets are deleted and replaced with the new set. This is intentional to maintain consistency.

4. **Time Format**: `sendTime` uses 24-hour format (HH:MM). Times should be in the server's timezone.

5. **Days Offset**:
   - Negative values: Before due date (e.g., -7 = 7 days before)
   - Zero: On due date
   - Positive values: After due date (e.g., 3 = 3 days after)

6. **Channels**: At least one channel must be specified. Multiple channels can be used simultaneously.

7. **Pagination**: List endpoint supports pagination with a maximum of 100 items per page.

8. **Filtering**: Use the `filters` query parameter with sequelize-api-paginate syntax for complex filtering.

---

## UI Flow Recommendations

### Creating a Policy

1. User fills in basic policy information:
   - Name
   - Reminder type (dropdown: Before Due, After Due, On Due Date)
   - Days offset (number input)
   - Send time (time picker)
   - Channels (multi-select checkboxes)
   - Status (toggle: Active/Inactive)

2. User selects targets:
   - Choose target type (dropdown: All, Building, Apartment, Room, Resident)
   - If not "All", select specific entities from a searchable list
   - Add multiple targets as needed
   - Display selected targets with their details

3. User confirms and submits

### Editing a Policy

1. Load existing policy details
2. Allow editing of all fields
3. For targets, show current targets and allow:
   - Adding new targets
   - Removing existing targets
   - Replacing all targets
4. Warn user that replacing targets will delete all existing targets

### Viewing Policies

1. Show list with pagination
2. Display key information: name, reminder type, days offset, status, target count
3. Click to view details
4. Details view shows full policy info with target details (names, codes, etc.)

### Deleting a Policy

1. Show confirmation dialog
2. Warn that this is a permanent deletion
3. Confirm before proceeding
