# DTR Correction — Frontend & ms-General Integration Guide

> **API Reference:** See [`dtr-correction-api.md`](./dtr-correction-api.md) for complete endpoint documentation, request/response schemas, and field values.

## Overview

The DTR Correction approval flow follows a **frontend-orchestrated** pattern (matching OT Authorization):

1. **Frontend** submits the DTR correction to **ms-timekeeping**
2. **Frontend** submits the approval request to **ms-general**  
3. **ms-general** calls back to **ms-timekeeping** when the decision is made
4. **Frontend** finalizes the approval on **ms-timekeeping**

```
Frontend                          ms-timekeeping                    ms-general
   │                                    │                              │
   │  (1) POST /api/v1/filing/dtr       │                              │
   │  ──────────────────────────────────►│                              │
   │    { is_filing: true, ... }        │                              │
   │                                    │                              │
   │  (2) POST /api/v1/approval-requests  │                              │
   │  ───────────────────────────────────────────────────────────────►│
   │    module_code: "dtr"              │                              │
   │    section_code: "Human Resources Division"                      │
   │    filed_by: 1001                  │                              │
   │    request_reference_id: "{id}"    │                              │
   │    callback_url: "/api/v1/approval/dtr"                          │
   │                                    │                              │
   │          ... approval workflow happens in ms-general ...           │
   │                                    │                              │
   │  (3) POST /api/v1/approval/dtr     │                              │
   │  ───────────────────────────────────►│                              │
   │    { id: [1], status: "approved" } │                              │
   │                                    │◄──── { success, updated, count } ─┤
   │                                    │                              │
   │  (4) GET /api/v1/dtr/{id} (verify) │                              │
   │  ──────────────────────────────────►│                              │
   │  ◄─── { status: "approved" } ──────┤                              │
   │                                    │                              │
```

## Key Difference from Previous Implementation

**Changed from backend-orchestrated to frontend-orchestrated:**
- Previously: ms-timekeeping automatically called ms-general when creating a filing
- Now: Frontend is responsible for calling both services, matching the OT authorization pattern
- Benefit: Gives frontend full control over the approval workflow timing and error handling

## Step-by-Step for Frontend

### Step 1: Get Employee Section Code (Pre-filing)

Before filing, get the employee's section code for the approval chain:

```
GET /api/v1/dtr/employee-section?employee_id=EMP001
```

**Response:**
```json
{
  "success": true,
  "data": {
    "employee_id": "EMP001",
    "section_code": "Human Resources Division"
  }
}
```

> **Note:** If no section is assigned, `section_code` will be `"DEFAULT"`.

### Step 2: Create DTR Correction (Filing)

```
POST /api/v1/filing/dtr
```

**Request Body:**
```json
{
  "is_filing": true,
  "employee_id": "EMP001",
  "date_correction": "2026-05-25",
  "schedule_date": "2026-05-22",
  "entry_type": "time_in",
  "corrected_time": "08:30:00",
  "justification": "Arrived late due to heavy traffic along EDSA.",
  "reason": "Late clock in",
  "created_by": "EMP001"
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `is_filing` | boolean | **yes** | `true` = goes through approval flow |
| `employee_id` | string | **yes** | Employee identifier |
| `date_correction` | date | **yes** | Date of correction request |
| `schedule_date` | date | **yes** | Schedule date being corrected |
| `entry_type` | string | **yes** | `"time_in"` or `"time_out"` |
| `corrected_time` | time | **yes** | The corrected clock time (H:i:s) |
| `justification` | text | **yes** | Explanation for the correction |
| `reason` | string | **yes** | Short reason label |
| `attachments` | file/array | no | Supporting documents |
| `created_by` | string | **yes** | Who created this |

**Response (201 Created):**
```json
{
  "success": true,
  "data": {
    "id": 1,
    "employee_id": "EMP001",
    "schedule_date": "2026-05-22",
    "entry_type": "time_in",
    "corrected_time": "08:30:00",
    "justification": "Arrived late due to heavy traffic along EDSA.",
    "status": "pending",
    "created_by": "EMP001",
    "created_at": "2026-05-25T10:00:00.000000Z",
    "updated_at": "2026-05-25T10:00:00.000000Z"
  },
  "message": "DTR created successfully"
}
```

**What happens server-side after this call:**
1. Validates payroll period is not locked
2. Creates the `dtr_corrections` record with `status = 'pending'`
3. Returns the created record to the frontend
4. **Does NOT** automatically call ms-general (frontend handles this)

### Step 3: Submit to ms-General for Approval

After getting the DTR correction ID from Step 2, submit an approval request to **ms-general**:

```
POST {ms-general-base-url}/api/v1/approval-requests
```

**Request Body:**
```json
{
  "module_code": "dtr",
  "section_code": "Human Resources Division",
  "filed_by": 1001,
  "request_reference_id": "1",
  "callback_url": "{frontend-url}/api/v1/approval/dtr"
}
```

| Field | Type | Description |
|-------|------|-------------|
| `module_code` | string | Always `"dtr"` for DTR corrections |
| `section_code` | string | Section/division code for routing |
| `filed_by` | int | Employee ID who filed |
| `request_reference_id` | string | DTR correction ID from ms-timekeeping |
| `callback_url` | string | Frontend endpoint to receive approval decision |

**Response:**
```json
{
  "success": true,
  "data": {
    "approval_request": {
      "id": 5001,
      "module_code": "dtr",
      "status": "pending"
    }
  }
}
```

Store the `approval_request_id` for tracking if needed.

### Step 4: Wait for Approval Decision

The approval workflow happens in ms-general. The frontend should either:
- **Poll** ms-general for the approval request status
- **Listen** for a webhook/event from ms-general
- **Let the user refresh** to check the status

Once ms-general returns the approval decision, proceed to Step 5.

### Step 5: Finalize on ms-Timekeeping

When ms-general returns **approved** or **rejected**, call ms-timekeeping to finalize:

```
POST /api/v1/approval/dtr
```

**If approved:**
```json
{
  "id": [1],
  "status": "approved",
  "remarks": "Approved per division head"
}
```

**If rejected:**
```json
{
  "id": [1],
  "status": "rejected",
  "remarks": "Insufficient justification"
}
```

**What happens on approval in ms-timekeeping:**
1. `dtr_corrections.status` → `approved`
2. Creates/updates `time_entry` with corrected time (preserving uncorrected fields)
3. Logs audit trail with before/after values

**Response:**
```json
{
  "success": true,
  "data": {
    "success": true,
    "updated": [1],
    "count": 1
  },
  "message": "DTR correction approval processed successfully"
}
```

## What Frontend Needs from Each Service

### From ms-timekeeping (`/api/v1`)

| Needed For | Endpoint | When |
|------------|----------|------|
| Employee section code | `GET /dtr/employee-section?employee_id=X` | Before filing (Step 1) |
| Create DTR correction | `POST /filing/dtr` | Step 2 |
| Finalize approval | `POST /approval/dtr` | Step 5 |
| Check correction status | `GET /dtr/{id}` | Verify final status |

### From ms-general

| Needed For | Endpoint | Who Calls | When |
|------------|----------|-----------|------|
| Create approval request | `POST /api/v1/approval-requests` | **Frontend** | After Step 2 |
| Check approval status | `GET /api/v1/approval-requests/{id}` | Frontend | Alternative to polling |

---

## ms-General: What to Implement

### Endpoint: POST /api/v1/approval-requests

Must accept DTR correction approval requests with:

```json
{
  "module_code": "dtr",
  "section_code": "Human Resources Division",
  "filed_by": 1001,
  "request_reference_id": "42",
  "callback_url": "https://frontend-domain/api/v1/approval/dtr"
}
```

| Field | Type | Description |
|-------|------|-------------|
| `module_code` | string | Always `"dtr"` for DTR corrections |
| `section_code` | string | Section/division code for routing |
| `filed_by` | int | Employee ID who filed |
| `request_reference_id` | string | DTR correction ID from ms-timekeeping |
| `callback_url` | string | Frontend must provide this for decision callback |

**Response:**
```json
{
  "success": true,
  "data": {
    "approval_request": {
      "id": 5001,
      "module_code": "dtr",
      "status": "pending"
    }
  }
}
```

### Callback: Frontend must provide and implement

When the approval workflow completes, ms-general must call back to the `callback_url` provided by the frontend:

```
POST {callback_url}
Content-Type: application/json

{
  "id": [1, 2, 3],
  "status": "approved",
  "remarks": "Approved per division head"
}
```

| Field | Type | Values |
|-------|------|--------|
| `id` | array | Array of DTR correction IDs |
| `status` | string | `"approved"` or `"rejected"` |
| `remarks` | string | Optional remarks |

**What frontend does on callback:**
- Verify the request came from ms-general (via shared secret or validation)
- Extract the IDs and status
- For each ID, call `POST /api/v1/approval/dtr` with the decision
- Update UI based on results

---

## Complete Frontend Sequence Pseudocode

```javascript
// Step 1: Get employee section code
const sectionRes = await api.get('/api/v1/dtr/employee-section', {
  params: { employee_id: 'EMP001' }
});
const sectionCode = sectionRes.data.data.section_code;

// Step 2: Create DTR correction
const created = await api.post('/api/v1/filing/dtr', {
  is_filing: true,
  employee_id: 'EMP001',
  date_correction: '2026-05-25',
  schedule_date: '2026-05-22',
  entry_type: 'time_in',
  corrected_time: '08:30:00',
  justification: 'Arrived late due to heavy traffic along EDSA.',
  reason: 'Late clock in',
  created_by: 'EMP001'
});
const dtrCorrectionId = created.data.data.id;

// Step 3: Submit to ms-general for approval
const approvalRes = await msGeneralApi.post('/api/v1/approval-requests', {
  module_code: 'dtr',
  section_code: sectionCode,
  filed_by: 1001,
  request_reference_id: dtrCorrectionId,
  callback_url: `${window.location.origin}/api/v1/approval/dtr`
});
const approvalRequestId = approvalRes.data.data.approval_request.id;

// Step 4: Poll or wait for approval result from ms-general
// (implementation depends on ms-general's mechanism)
// For this example, we'll simulate receiving the decision:
// const decision = await waitForApprovalDecision(approvalRequestId);
const decision = { status: 'approved' }; // or 'rejected'

// Step 5: When ms-general returns the decision, finalize on ms-timekeeping
const finalizeRes = await api.post('/api/v1/approval/dtr', {
  id: [dtrCorrectionId],
  status: decision.status,
  remarks: decision.status === 'approved' 
    ? 'Approved per division head' 
    : 'Insufficient justification'
});

if (decision.status === 'approved') {
  showSuccess('DTR correction approved and synced to your time record.');
} else {
  showError('DTR correction was rejected.');
}
```