Files
lcbp3/specs/06-Decision-Records/ADR-003-api-design-strategy.md
T
admin c95e0f537e
CI / CD Pipeline / build (push) Successful in 4m34s
CI / CD Pipeline / deploy (push) Successful in 7m33s
690404:1139 Modify ADR
2026-04-04 11:39:56 +07:00

14 KiB

ADR-003: API Design Strategy

Status: Accepted (Implementation Ready) Date: 2026-04-04 Decision Makers: Development Team, System Architect Related Documents:


🎯 Gap Analysis & Purpose

ปิด Gap จากเอกสาร:

  • API Design & Error Handling - Section 2: "ระบบต้องใช้ RESTful Principles และมีความสอดคล้องกัน"
    • เหตุผล: ต้องการบันทึกการตัดสินใจเกี่ยวกับ API Design Patterns ที่ใช้จริงในระบบ
  • Backend Guidelines - Section 3: "การออกแบบ API ต้องรองรับ TypeScript และ NestJS Patterns"
    • เหตุผล: ต้องการทำให้ API Design สอดคล้องกับ NestJS Ecosystem

แก้ไขความขัดแย้ง:

  • REST Purity vs Pragmatic API Design: ต้องการความสวยงามของ REST แต่ต้องรองรับ Business Logic ที่ซับซ้อน
    • การตัดสินใจนี้ช่วยแก้ไขโดย: ใช้ RESTful หลักแต่เพิ่ม Pragmatic Patterns สำหรับ Workflow และ Business Operations

Context and Problem Statement

LCBP3-DMS ต้องการ API Design ที่:

  1. Consistent: ทุก Endpoint ใช้ Patterns เดียวกัน
  2. Type-Safe: รองรับ TypeScript และ DTO Validation
  3. Business-Ready: รองรับ Workflow Operations และ Complex Business Logic
  4. Document-Driven: Auto-generate Swagger Documentation
  5. Performance-Oriented: รองรับ Pagination, Filtering, และ Caching

Key Challenges

  1. Resource Naming: การตั้งชื่อ Resources ที่สะท้อน Business Domain
  2. Complex Operations: Workflow transitions, Document numbering ที่ไม่ใช่ CRUD ธรรมดา
  3. Response Consistency: การคืนค่าที่สม่ำเสมอทั้ง Single และ Collection
  4. Error Handling: การจัดการ Business Exceptions และ Validation Errors
  5. Versioning: การเตรียมพร้อมสำหรับ API Evolution

Decision Drivers

  • Developer Experience: ง่ายต่อการใช้งานและ Debug
  • Type Safety: ป้องกัน Runtime Errors ด้วย TypeScript
  • Business Alignment: API สะท้อน Business Processes จริง
  • Performance: รองรับ High-volume Operations
  • Documentation: Auto-generated และ Up-to-date
  • Testing: ง่ายต่อการ Unit Test และ Integration Test

Considered Options

Option 1: Pure REST with Resource Endpoints Only

แนวทาง: ใช้ REST Resources เท่านั้น ไม่มี Action Endpoints

Pros:

  • RESTful purity
  • Simple to understand
  • Standard HTTP semantics

Cons:

  • Difficult for complex business operations
  • Workflow transitions become awkward
  • Document numbering doesn't fit resource model

Option 2: RPC-style with Action Endpoints

แนวทาง: ใช้ Action Endpoints สำหรับทุก Business Operation

Pros:

  • Clear business intent
  • Easy for complex operations
  • Direct mapping to use cases

Cons:

  • Not RESTful
  • Inconsistent patterns
  • Hard to document with Swagger

Option 3: Hybrid REST + Action Endpoints (Selected)

แนวทาง: REST สำหรับ CRUD และ Action Endpoints สำหรับ Business Operations

Pros:

  • Best of Both Worlds: REST ที่เหมาะสม + Actions ที่ชัดเจน
  • Business Clarity: Workflow actions อยู่ใน endpoints ที่เข้าใจง่าย
  • Type Safety: DTOs สำหรับทุก operation
  • Documentation: Swagger สามารถ document ได้ทั้งสองแบบ
  • Consistency: Clear naming conventions

Cons:

  • Slightly more complex
  • Requires developer discipline

Decision Outcome

Chosen Option: Option 3 - Hybrid REST + Action Endpoints

Rationale

เลือก Hybrid Approach เนื่องจาก:

  1. Business Reality: DMS มี Operations ที่ซับซ้อน (Workflow, Numbering) ที่ไม่ fit กับ pure REST
  2. Developer Experience: Actions ชัดเจนกว่าการยัด business logic ลงใน PATCH
  3. Maintainability: แยก concerns ระหว่าง data access และ business operations
  4. Scalability: สามารถเพิ่ม business operations ได้โดยไม่ทำให้ REST resources ซับซ้อน

🔍 Impact Analysis

Affected Components (ส่วนประกอบที่ได้รับผลกระทบ)

Component Level Impact Description Required Action
API Controllers 🔴 High ต้องใช้ Hybrid Pattern สำหรับทุก Module Refactor controllers
DTOs 🔴 High ต้องสร้าง DTOs สำหรับทุก Endpoint Create comprehensive DTOs
Documentation 🟡 Medium Swagger ต้อง cover ทั้ง REST และ Actions Update Swagger config
Frontend API Client 🟡 Medium ต้องรองรับทั้งสอง pattern Update API service calls
Testing 🟡 Medium ต้อง test ทั้ง resource และ action endpoints Add integration tests

Required Changes (การเปลี่ยนแปลงที่ต้องดำเนินการ)

🔴 Critical Changes (ต้องทำทันที)

  • Define API Standards - สร้างมาตรฐานการตั้งชื่อและ patterns
  • Refactor Correspondence API - ใช้ hybrid pattern
  • Update RFA API - ใช้ action endpoints สำหรับ workflow
  • Create Base Controller - shared patterns และ utilities

🟡 Important Changes (ควรทำภายใน 1 สัปดาห์)

  • Update API Documentation - Swagger พร้อม examples
  • Create API Client Library - frontend TypeScript client
  • Add Integration Tests - test ทุก endpoint patterns
  • Performance Testing - ตรวจสอบ response times

🟢 Nice-to-Have (ทำถ้ามีเวลา)

  • API Versioning Strategy - prepare for v2
  • OpenAPI Generator - auto-generate clients
  • API Analytics - track usage patterns

Implementation Details

API Design Patterns

1. Resource Endpoints (REST)

// Standard CRUD operations
GET    /api/v1/correspondences           // List with pagination
GET    /api/v1/correspondences/:id       // Get by UUID
POST   /api/v1/correspondences           // Create
PUT    /api/v1/correspondences/:id       // Full update
PATCH  /api/v1/correspondences/:id       // Partial update
DELETE /api/v1/correspondences/:id       // Soft delete

2. Action Endpoints (Business Operations)

// Workflow actions
POST /api/v1/correspondences/:id/submit
POST /api/v1/correspondences/:id/approve
POST /api/v1/correspondences/:id/reject
POST /api/v1/correspondences/:id/forward

// Document numbering
POST /api/v1/document-numbering/reserve
POST /api/v1/document-numbering/generate

// Bulk operations
POST /api/v1/correspondences/bulk-update
POST /api/v1/correspondences/bulk-approve

// Reports and exports
GET /api/v1/reports/correspondence-summary
GET /api/v1/exports/correspondences/:format

Response Format Standards

Success Response (Single Resource)

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000", // UUID (ADR-019)
    "documentNumber": "LCBP3-CORR-2024-0001",
    "subject": "Meeting minutes",
    "status": "SUBMITTED",
    "createdAt": "2024-01-01T00:00:00Z",
    "updatedAt": "2024-01-01T00:00:00Z"
  },
  "meta": {
    "timestamp": "2024-01-01T00:00:00Z",
    "version": "1.0"
  }
}

Success Response (Collection)

{
  "data": [
    { "id": "...", "documentNumber": "...", ... },
    { "id": "...", "documentNumber": "...", ... }
  ],
  "meta": {
    "pagination": {
      "page": 1,
      "limit": 20,
      "total": 100,
      "totalPages": 5
    },
    "filters": {
      "status": "SUBMITTED",
      "dateFrom": "2024-01-01"
    },
    "timestamp": "2024-01-01T00:00:00Z"
  }
}

Action Response

{
  "data": {
    "action": "approve",
    "result": "SUCCESS",
    "nextStatus": "APPROVED",
    "workflow": {
      "id": "wf-123",
      "currentState": "APPROVED",
      "previousState": "PENDING_APPROVAL"
    }
  },
  "meta": {
    "timestamp": "2024-01-01T00:00:00Z",
    "processedBy": "user-456"
  }
}

Error Response Format

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed on input data",
    "statusCode": 400,
    "timestamp": "2024-01-01T00:00:00Z",
    "path": "/api/v1/correspondences",
    "details": [
      {
        "field": "subject",
        "message": "Subject is required and must be at least 10 characters",
        "value": null
      }
    ]
  }
}

Naming Conventions

URL Paths

  • Resources: Plural nouns, kebab-case
    • /correspondences, /projects, /organizations
  • Actions: Verb-noun pattern, kebab-case
    • /correspondences/:id/submit, /document-numbering/generate
  • Nested Resources: Parent-child relationship
    • /projects/:id/contracts, /contracts/:id/correspondences

JSON Properties

  • Properties: camelCase
    • documentNumber, createdAt, primaryOrganizationId
  • Enums: UPPER_SNAKE_CASE
    • "SUBMITTED", "IN_REVIEW", "APPROVED"
  • Booleans: is/has prefix
    • isActive, hasAttachments, canEdit

DTO Examples

Create DTO

import { IsString, IsOptional, IsEnum, IsUUID } from 'class-validator';

export class CreateCorrespondenceDto {
  @IsString()
  @MinLength(10)
  subject: string;

  @IsOptional()
  @IsString()
  content?: string;

  @IsEnum(['LETTER', 'RFI', 'MEMO', 'NOTICE'])
  type: CorrespondenceType;

  @IsUUID()
  @IsOptional()
  originatorId?: string;

  @IsUUID()
  projectId: string;

  @IsArray()
  @IsUUID(4, { each: true })
  recipientIds: string[];
}

Action DTO

export class ApproveCorrespondenceDto {
  @IsString()
  @MaxLength(1000)
  comment?: string;

  @IsOptional()
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => AttachmentDto)
  attachments?: AttachmentDto[];
}

Consequences

Positive

  1. Business Clarity: Actions สะท้อน business operations ชัดเจน
  2. Type Safety: DTOs ป้องกัน runtime errors
  3. Consistency: Standard patterns ทั่วทั้ง API
  4. Documentation: Auto-generated Swagger ครบถ้วน
  5. Maintainability: แยก concerns ระหว่าง data และ business logic
  6. Testing: ง่ายต่อการ test ทุก endpoint

Negative

  1. Learning Curve: ต้องเรียนรู้ hybrid patterns
  2. Documentation Complexity: ต้องอธิบายทั้ง REST และ Actions
  3. API Surface Area: มี endpoints มากขึ้น

Mitigation Strategies

  • Learning Curve: Create comprehensive API guidelines and examples
  • Documentation: Use Swagger groups and descriptions
  • API Surface: Group related endpoints และใช้ consistent patterns

🔄 Review Cycle & Maintenance

Review Schedule

  • Next Review: 2026-10-04 (6 months from creation)
  • Review Type: Scheduled (API Strategy Review)
  • Reviewers: System Architect, Backend Team Lead, Frontend Team Lead

Review Checklist

  • ยังคงตอบโจทย์ Business Requirements หรือไม่?
  • มี API patterns ใหม่ที่ควรพิจารณาหรือไม่?
  • มีปัญหา Performance หรือ Usability หรือไม่?
  • ต้องการ Update หรือ Deprecate patterns ใดหรือไม่?

Version History

Version Date Changes Status
1.0 2026-04-04 Initial version - Hybrid REST + Action Strategy Accepted

Compliance

เป็นไปตาม:



References