Private Docs

API Spec — Edit-History + RefNo + ServiceId Filter

API ที่เพิ่ม/แก้: edit-history aggregate (owner+admin), step-data +refNo, admin-list filter ด้วย serviceId (Codex appId) — พร้อม sequence diagram + req/response

อัปเดต: 2026-06-25

ขอบเขต: API ที่เพิ่ม/แก้ใน session นี้ — edit-history aggregate, step-data + refNo, admin-list filter ด้วย serviceId Service: user-service (Backend_UserService) · Gateway: APIM exim-az-hub-apim → DEV UserService API (userservice-api) Base: https://gateway-dev.exim.go.th/userservice-api + /api/user-service/v1 Response envelope: ทุก endpoint ห่อด้วย ApiResponse<T> = { "data": T, "meta": {...} } 🆕 = field/endpoint ที่เพิ่มใหม่ · ✏️ = แก้ไข


1. ภาพใหญ่ (Big Picture)

graph LR
  subgraph FE["Frontend (sa-onboarding-demo)"]
    A1["Admin: รายละเอียดใบสมัคร<br/>/admin/onboarding-requests/:id"]
    A2["Admin: รายการคำขอ (list)<br/>/admin/onboarding-requests"]
    R1["Requestor: ประวัติการแก้ไข<br/>/corporate-workspace/:id/edit-history"]
    R2["Requestor: ประวัติสถานะ<br/>/corporate-workspace/:id/status-history"]
  end
  subgraph GW["APIM Gateway"]
    P["DEV UserService API<br/>(userservice-api)"]
  end
  subgraph BE["UserService API (.NET)"]
    O["OnboardingController"]
    H["GetEditHistory / GetAdminEditHistory<br/>GetStepData / AdminList handlers"]
  end
  CDX["Codex API<br/>(app registry)"]

  A1 -->|"GET summary / step-map / step-data / history / edit-history(admin)"| P
  A2 -->|"GET admin/flow-instances ?serviceId="| P
  A2 -.->|"GET apps (filter options + lookup)"| CDX
  R1 -->|"GET onboarding/.../edit-history (owner)"| P
  R2 -->|"GET onboarding/.../history (owner)"| P
  P --> O --> H --> DB[("PostgreSQL<br/>FlowInstance / History")]

  classDef new fill:#d4f7d4,stroke:#2e7d32,color:#1b5e20;
  classDef chg fill:#fff4cc,stroke:#b8860b,color:#7a5a00;
  class R1,R2 new;
  class A1,A2 chg;

3 features ของ session นี้

#Featureใช้ที่ไหน
1🆕 edit-history aggregate (owner + admin แยก route)Admin tab “ประวัติการแก้ไข” + Requestor หน้า edit-history
2🆕 refNo ใน step-data responseAdmin/Requestor onboarding-runner (step detail)
3🆕 filter admin-list ด้วย serviceId (Codex appId)Admin หน้ารายการคำขอ (column “บริการ” + filter)

2. สรุปการเปลี่ยนแปลง (Added / Removed)

EndpointMethodเปลี่ยนอะไร
/onboarding/instances/{id}/edit-historyGET🆕 เพิ่มใหม่ (owner)
/admin/flow-instances/{id}/edit-historyGET🆕 เพิ่มใหม่ (admin, Draft = forbidden)
/onboarding/instances/{id}/steps/{stepType}/dataGET✏️ response +refNo
/admin/flow-instances/{id}/steps/{stepType}/dataGET✏️ response +refNo
/admin/flow-instancesGET✏️ query +serviceId (repeated, Guid)

ไม่มีอะไรลบออกจาก API (เฉพาะ APIM ลบ 2 stale ops /users/{userId}/.../permissions ที่ backend ไม่มีแล้ว เพื่อ sync ให้ตรง — ดู §6)


3. API Spec รายเส้น

3.1 🆕 GET /onboarding/instances/{id}/edit-history (Owner)

ทุกรอบการแก้ไข (Rework→Resubmit) + comment ธนาคารราย step ในก้อนเดียว — owner เห็นใบตัวเอง

Request

ส่วนค่า
pathid : Guid (FlowInstanceId)
authowner (cookie __Host-onboarding / JWT) · dev = AllowAnonymous

Response 200 · ApiResponse<EditHistoryDto>

{
  "data": {
    "rounds": [                         // เรียงรอบล่าสุดก่อน
      {
        "roundNo": 2,                   // "รอบการแก้ไขครั้งที่ N"
        "isLatest": true,               // badge "ล่าสุด"
        "bankRequestedAt": "2026-06-10T00:00:00Z",   // "ธนาคารแจ้งให้แก้ไข"
        "resubmittedAt": "2026-06-13T00:00:00Z",     // "แก้ไขและยื่นคำขอล่าสุด" (null = ยังไม่ยื่นกลับ)
        "corrections": [                // comment จัดกลุ่มตาม step
          {
            "stepType": "DesignateCustomersStep",
            "stepLabel": "ข้อมูลผู้ใช้งาน",          // จาก StepCatalog
            "notes": [
              "ผู้ใช้งานลำดับที่ 2 : ชื่อ-นามสกุลไม่ตรงกับเอกสารยืนยันตัวตน",
              "ผู้ใช้งานลำดับที่ 3 : ไม่พบเอกสารประกอบการสมัคร"
            ]
          }
        ]
      }
    ]
  },
  "meta": { "apiVersion": "v1", "processingTime": "5ms" }
}

ที่มา: derive จาก FlowInstanceHistory rows + ReworkContextJsonไม่มี table/column ใหม่


3.2 🆕 GET /admin/flow-instances/{id}/edit-history (Admin)

shape เหมือน 3.1 เป๊ะ — ต่างแค่ guard: Draft → 403 + admin เห็นใบที่ ≥ Submitted

Response 200 = เหมือน 3.1 · 403 ถ้าใบเป็น Draft

// 403
{ "data": null, "meta": { "errorCode": "Application.Forbidden", "message": "ไม่มีสิทธิ์ดูใบสมัครสถานะ Draft" } }

3.3 ✏️ GET /onboarding/instances/{id}/steps/{stepType}/data (+ /admin/flow-instances/{id}/...)

ข้อมูล step เดียว — เพิ่ม refNo ใน response

Request

ส่วนค่า
pathid : Guid · stepType : string (เช่น CompanyInfoStep)

Response 200 · ApiResponse<StepDataDto>

{
  "data": {
    "stepType": "CompanyInfoStep",
    "refNo": "FXO-2025-00001234",   // 🆕 เลขที่คำขอ (null ถ้ายังไม่ issue RefNo)
    "canViewData": true,
    "secured": false,                // true = sensitive (ไม่ส่ง data)
    "dataJson": "{ ... }"            // null ถ้า secured / ดูไม่ได้
  },
  "meta": { "apiVersion": "v1" }
}

3.4 ✏️ GET /admin/flow-instances — filter ด้วย serviceId

เพิ่ม query serviceId (repeated, Guid = Codex appId). flowCode ยังคงไว้เพื่อ compat

Request — query params

paramtypeหมายเหตุ
statusstring[] (repeated)bucket สถานะ
keywordstringRefNo / ชื่อบริษัท
submittedFrom / submittedTodate (YYYY-MM-DD)ช่วงวันที่ยื่น
page / pageSizeintpaging
sortBy / sortDirstringrefNo|status|submittedAt|lastActionAt · asc|desc
flowCodestring[] (repeated)[legacy]
🆕 serviceIdGuid[] (repeated)filter ตาม service (Codex appId)

ตัวอย่าง: GET /admin/flow-instances?status=Submitted&serviceId=2f1c...&serviceId=9a3b...&page=1&pageSize=10

Response 200 · ApiResponse<PagedResult<FlowInstanceSummaryDto>>

{
  "data": {
    "items": [
      {
        "flowInstanceId": "e32cf739-...",
        "refNo": "FXO-2025-00001234",
        "flowCode": "NEW_REQUESTOR",
        "serviceId": "2f1c8d40-...",     // Codex appId → FE lookup ชื่อบริการ
        "serviceName": "FX Online",
        "companyName": "A Company จำกัด (มหาชน)",
        "status": "Submitted",
        "submittedAt": "2026-06-18T15:22:00Z",
        "lastActorName": "ธนาคาร",
        "lastActionAt": "2026-06-18T15:22:00Z"
      }
    ],
    "totalCount": 230, "pageNumber": 1, "pageSize": 10, "totalPages": 23,
    "hasNextPage": true, "hasPreviousPage": false
  },
  "meta": { "apiVersion": "v1" }
}

4. Sequence Diagrams (ลำดับการ call)

4.1 Admin — หน้ารายละเอียดใบสมัคร (info bar + 3 tabs)

sequenceDiagram
  autonumber
  participant U as Admin
  participant FE as Admin Detail Page
  participant API as UserService API

  U->>FE: เปิด /admin/onboarding-requests/{id}
  FE->>API: GET /admin/flow-instances/{id}
  API-->>FE: FlowInstanceSummaryDto (info bar)

  Note over FE: Tab 1 — รายละเอียดใบสมัคร (lazy)
  FE->>API: GET /admin/flow-instances/{id}/step-map
  API-->>FE: StepMapDto (รายการ step)
  U->>FE: กดเลือก section
  FE->>API: GET /admin/flow-instances/{id}/steps/{stepType}/data
  API-->>FE: StepDataDto (+refNo) 🆕

  Note over FE: Tab 2 — ประวัติสถานะ
  FE->>API: GET /onboarding/instances/{id}/history
  API-->>FE: HistoryListDto (timeline)

  Note over FE: Tab 3 — ประวัติการแก้ไข 🆕
  FE->>API: GET /admin/flow-instances/{id}/edit-history
  API-->>FE: EditHistoryDto (rounds + comments)

4.2 Requestor — หน้าประวัติการแก้ไข 🆕

sequenceDiagram
  autonumber
  participant U as Requestor
  participant FE as Edit-History Page
  participant API as UserService API
  U->>FE: เปิด /corporate-workspace/{id}/edit-history
  FE->>API: GET /onboarding/instances/{id}/edit-history (owner)
  API-->>FE: EditHistoryDto
  Note over FE: "จำนวนครั้งที่แก้ไข" = rounds.length<br/>render การ์ดต่อรอบ + timeline + comment ราย step

4.3 Admin — รายการคำขอ + filter ด้วย serviceId 🆕

sequenceDiagram
  autonumber
  participant U as Admin
  participant FE as Admin List Page
  participant CDX as Codex API
  participant API as UserService API

  U->>FE: เปิด /admin/onboarding-requests
  FE->>CDX: GET /apps  (filter options + lookup ชื่อบริการ)
  CDX-->>FE: AppRegistration[] (id + appName)
  FE->>API: GET /admin/flow-instances?status=...&page=1
  API-->>FE: PagedResult (column "บริการ" = lookup serviceId→appName)

  U->>FE: เลือกบริการใน filter → นำไปใช้
  FE->>API: GET /admin/flow-instances?serviceId={appId}&... 🆕
  API-->>FE: PagedResult (กรองตาม serviceId)

5. Auth / Role (สรุป)

EndpointRoleGuard
/onboarding/.../edit-historyOwnerเห็นใบตัวเอง (cookie/JWT); dev = pass
/admin/.../edit-historyAdminDraft = 403; เห็นใบ ≥ Submitted
/...steps/{stepType}/dataOwner/Adminroute แยก role (owner-guard / admin Draft-forbid)
/admin/flow-instancesAdmindev = AllowAnonymous (pre-SIT ใส่ RBAC)

6. APIM sync (2026-06-25)

sync DEV UserService API บน APIM ให้ เท่ากับ spec จาก pod (119 paths = 119 paths):

  • เพิ่ม 6 ops ที่ขาด (รวม edit-history × 2, application-report × 2, users/me/*permissions × 3) — method/url-template ตรง spec
  • ลบ 2 stale ops /users/{userId}/.../permissions (backend เปลี่ยนเป็น /users/me/... แล้ว)
  • ทำแบบ targeted op add/delete (ไม่ full-import) — routing policy / serviceUrl / props ไม่ถูกแตะ

หมายเหตุ: serviceId query param (3.4) ยังไม่อยู่ใน spec ที่ deploy (PR #858 รอ approve) — APIM forward query param ให้เองอยู่แล้ว จึงใช้งานได้เมื่อ backend deploy