openapi: 3.1.0
info:
  title: CLQMS - Clinical Laboratory Quality Management System API
  description: |
    API for Clinical Laboratory Quality Management System supporting patient management,
    specimen tracking, test ordering, instrument integration, and laboratory operations.

    **IMPORTANT:** For OpenAPI tools (Swagger UI, Redoc, Postman, etc.), use the bundled file:
    `api-docs.bundled.yaml` which contains all paths and schemas merged into one file.

    This file (api-docs.yaml) contains schema references and is meant for development.
    The paths are defined in separate files in the `paths/` directory.
  version: 1.0.0
  contact:
    name: CLQMS API Support
  license:
    name: Proprietary
servers:
  - url: http://localhost/clqms01/
    description: Local development server
  - url: https://clqms01-api.services-summit.my.id/
    description: Production server
tags:
  - name: Authentication
    description: User authentication and session management
  - name: Patient
    description: Patient registration and management
  - name: Patient Visit
    description: Patient visit/encounter management
  - name: Organization
    description: Organization structure (accounts, sites, disciplines, departments, workstations)
  - name: Location
    description: Location management (rooms, wards, buildings)
  - name: Equipment
    description: Laboratory equipment and instrument management
  - name: Specimen
    description: Specimen and container management
  - name: Test
    description: Test definitions and test catalog
  - name: Rule
    description: Rule engine - rules can be linked to multiple tests via testrule mapping table
  - name: Calculation
    description: Lightweight calculator endpoint for retrieving computed values by code or name
  - name: Order
    description: Laboratory order management
  - name: Result
    description: Patient results reporting with auto-validation
  - name: Report
    description: Lab report generation (HTML view)
  - name: Edge API
    description: Instrument integration endpoints
  - name: Contact
    description: Contact management (doctors, practitioners, etc.)
  - name: ValueSet
    description: Value set definitions and items
  - name: User
    description: User management and administration
  - name: Demo
    description: Demo/test endpoints (no authentication)
  - name: Audit
    description: Audit log retrieval and filtering
paths:
  /api/audit-logs:
    get:
      tags:
        - Audit
      summary: Retrieve audit log entries for a table
      security:
        - bearerAuth: []
      parameters:
        - name: table
          in: query
          required: true
          schema:
            type: string
          description: Table alias for the audit data (logpatient, logorder, logmaster, logsystem)
        - name: rec_id
          in: query
          schema:
            type: string
          description: Primary record identifier (RecID) to filter audit rows
        - name: event_id
          in: query
          schema:
            type: string
          description: Canonical EventID (case insensitive)
        - name: activity_id
          in: query
          schema:
            type: string
          description: Canonical ActivityID (case insensitive)
        - name: from
          in: query
          schema:
            type: string
            format: date-time
          description: Lower bound for LogDate inclusive
        - name: to
          in: query
          schema:
            type: string
            format: date-time
          description: Upper bound for LogDate inclusive
        - name: search
          in: query
          schema:
            type: string
          description: Search term that matches user, reason, field names, or values
        - name: page
          in: query
          schema:
            type: integer
            default: 1
          description: Page number
        - name: perPage
          in: query
          schema:
            type: integer
            default: 20
          description: Items per page (max 100)
      responses:
        '200':
          description: Audit log results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuditLogsEnvelope'
        '400':
          description: Validation failure (missing table or invalid filters)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuditLogsErrorResponse'
        '500':
          description: Internal error when retrieving audit logs
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuditLogsErrorResponse'
  /api/auth/login:
    post:
      tags:
        - Authentication
      summary: User login
      description: Authenticate user and receive JWT token via HTTP-only cookie
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/LoginRequest'
      responses:
        '200':
          description: Login successful
          headers:
            Set-Cookie:
              description: JWT token in HTTP-only cookie
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LoginResponse'
        '400':
          description: Missing username
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Invalid credentials
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/auth/logout:
    post:
      tags:
        - Authentication
      summary: User logout
      description: Clear JWT token cookie
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Logout successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
  /api/auth/check:
    get:
      tags:
        - Authentication
      summary: Check authentication status
      security:
        - bearerAuth: []
        - cookieAuth: []
      responses:
        '200':
          description: Authenticated
          content:
            application/json:
              schema:
                type: object
                properties:
                  authenticated:
                    type: boolean
                  user:
                    type: object
        '401':
          description: Not authenticated
  /api/auth/register:
    post:
      tags:
        - Authentication
      summary: Register new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterRequest'
      responses:
        '201':
          description: User created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
  /api/auth/change_pass:
    post:
      tags:
        - Authentication
      summary: Change password
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - current_password
                - new_password
              properties:
                current_password:
                  type: string
                  format: password
                new_password:
                  type: string
                  format: password
      responses:
        '200':
          description: Password changed successfully
  /v2/auth/login:
    post:
      tags:
        - Authentication
      summary: V2 User login
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
      responses:
        '200':
          description: Login successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LoginResponse'
  /v2/auth/logout:
    post:
      tags:
        - Authentication
      summary: V2 User logout
      responses:
        '200':
          description: Logout successful
  /v2/auth/check:
    get:
      tags:
        - Authentication
      summary: V2 Check authentication
      responses:
        '200':
          description: Auth check result
  /v2/auth/register:
    post:
      tags:
        - Authentication
      summary: V2 Register new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterRequest'
      responses:
        '201':
          description: User created
  /api/calc/testcode/{codeOrName}:
    post:
      tags:
        - Calculation
      summary: Evaluate a configured calculation by test code or name and return the raw result map.
      security: []
      parameters:
        - name: codeOrName
          in: path
          required: true
          schema:
            type: string
          description: TestSiteCode or TestSiteName of the calculated test (case-insensitive).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: Key-value pairs where keys match member tests used in the formula.
              additionalProperties:
                type: number
            example:
              TBIL: 5
              DBIL: 3
      responses:
        '200':
          description: Returns a single key/value pair with the canonical TestSiteCode or an empty object when the calculation is incomplete or missing.
          content:
            application/json:
              schema:
                type: object
              examples:
                success:
                  value:
                    IBIL: 2
                incomplete:
                  value: {}
  /api/calc/testsite/{testSiteID}:
    post:
      tags:
        - Calculation
      summary: Evaluate a calculation defined for a test site and return a structured result.
      security: []
      parameters:
        - name: testSiteID
          in: path
          required: true
          schema:
            type: integer
          description: Identifier for the test site whose definition should be evaluated.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: Variable assignments required by the test site formula.
              additionalProperties:
                type: number
            example:
              result: 85
              gender: female
              age: 30
      responses:
        '200':
          description: Returns the calculated result, testSiteID, formula code, and echoed variables.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    type: object
                    properties:
                      result:
                        type: number
                      testSiteID:
                        type: integer
                      formula:
                        type: string
                      variables:
                        type: object
                        additionalProperties:
                          type: number
              examples:
                success:
                  value:
                    status: success
                    data:
                      result: 92.4
                      testSiteID: 123
                      formula: '{result} * {factor} + {age}'
                      variables:
                        result: 85
                        gender: female
                        age: 30
        '404':
          description: No calculation defined for the requested test site.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: failed
                  message:
                    type: string
                    example: No calculation defined for this test site
  /api/contact:
    get:
      tags:
        - Contact
      summary: List contacts
      security:
        - bearerAuth: []
      parameters:
        - name: ContactName
          in: query
          schema:
            type: string
          description: Filter by contact name (searches in NameFirst and NameLast)
        - name: Specialty
          in: query
          schema:
            type: string
          description: Filter by medical specialty code
      responses:
        '200':
          description: List of contacts
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Contact'
    post:
      tags:
        - Contact
      summary: Create new contact
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - NameFirst
              properties:
                NameFirst:
                  type: string
                  description: First name
                NameLast:
                  type: string
                  description: Last name
                Title:
                  type: string
                  description: Title (e.g., Dr, Mr, Mrs)
                Initial:
                  type: string
                  description: Middle initial
                Birthdate:
                  type: string
                  format: date-time
                  description: Date of birth
                EmailAddress1:
                  type: string
                  format: email
                  description: Primary email address
                EmailAddress2:
                  type: string
                  format: email
                  description: Secondary email address
                Phone:
                  type: string
                  description: Primary phone number
                MobilePhone1:
                  type: string
                  description: Primary mobile number
                MobilePhone2:
                  type: string
                  description: Secondary mobile number
                Specialty:
                  type: string
                  description: Medical specialty code
                SubSpecialty:
                  type: string
                  description: Sub-specialty code
      responses:
        '201':
          description: Contact created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      tags:
        - Contact
      summary: Delete contact
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - ContactID
              properties:
                ContactID:
                  type: integer
                  description: Contact ID to delete
      responses:
        '200':
          description: Contact deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
  /api/contact/{id}:
    get:
      tags:
        - Contact
      summary: Get contact by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Contact ID
      responses:
        '200':
          description: Contact details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/Contact'
    patch:
      tags:
        - Contact
      summary: Update contact
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Contact ID to update
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - NameFirst
              properties:
                NameFirst:
                  type: string
                  description: First name
                NameLast:
                  type: string
                  description: Last name
                Title:
                  type: string
                  description: Title (e.g., Dr, Mr, Mrs)
                Initial:
                  type: string
                  description: Middle initial
                Birthdate:
                  type: string
                  format: date-time
                  description: Date of birth
                EmailAddress1:
                  type: string
                  format: email
                  description: Primary email address
                EmailAddress2:
                  type: string
                  format: email
                  description: Secondary email address
                Phone:
                  type: string
                  description: Primary phone number
                MobilePhone1:
                  type: string
                  description: Primary mobile number
                MobilePhone2:
                  type: string
                  description: Secondary mobile number
                Specialty:
                  type: string
                  description: Medical specialty code
                SubSpecialty:
                  type: string
                  description: Sub-specialty code
      responses:
        '201':
          description: Contact updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/demo/hello:
    get:
      tags:
        - Demo
      summary: Hello world endpoint
      description: Simple test endpoint that returns a greeting message
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                    example: Hello, World!
  /api/demo/ping:
    get:
      tags:
        - Demo
      summary: Ping endpoint
      description: Health check endpoint to verify API is running
      responses:
        '200':
          description: API is running
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                    example: pong
                  timestamp:
                    type: string
                    format: date-time
  /api/edge/result:
    post:
      tags:
        - Edge API
      summary: Receive results from instrument (tiny-edge)
      description: |
        Receives instrument results and stores them in the edgeres table for processing.
        This endpoint is typically called by the tiny-edge middleware connected to laboratory analyzers.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EdgeResultRequest'
      responses:
        '201':
          description: Result received and queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EdgeResultResponse'
        '400':
          description: Invalid JSON payload
  /api/edge/order:
    get:
      tags:
        - Edge API
      summary: Fetch pending orders for instruments
      description: Returns orders that need to be sent to laboratory instruments for testing
      parameters:
        - name: instrument_id
          in: query
          schema:
            type: string
          description: Filter by instrument
        - name: status
          in: query
          schema:
            type: string
          enum:
            - pending
            - acknowledged
          description: Filter by status
      responses:
        '200':
          description: List of orders
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/EdgeOrder'
  /api/edge/order/{orderId}/ack:
    post:
      tags:
        - Edge API
      summary: Acknowledge order delivery
      description: Mark order as acknowledged by the instrument
      parameters:
        - name: orderId
          in: path
          required: true
          schema:
            type: integer
          description: Edge order ID
      responses:
        '200':
          description: Order acknowledged
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
  /api/edge/status:
    post:
      tags:
        - Edge API
      summary: Log instrument status update
      description: Receive status updates from laboratory instruments
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - instrument_id
                - status
              properties:
                instrument_id:
                  type: string
                status:
                  type: string
                  enum:
                    - online
                    - offline
                    - error
                    - maintenance
                message:
                  type: string
                timestamp:
                  type: string
                  format: date-time
      responses:
        '200':
          description: Status logged
  /api/equipmentlist:
    get:
      tags:
        - Equipment
      summary: List equipment
      description: Get list of equipment with optional filters
      security:
        - bearerAuth: []
      parameters:
        - name: IEID
          in: query
          schema:
            type: string
          description: Filter by IEID
        - name: InstrumentName
          in: query
          schema:
            type: string
          description: Filter by instrument name
        - name: DepartmentID
          in: query
          schema:
            type: integer
          description: Filter by department ID
        - name: WorkstationID
          in: query
          schema:
            type: integer
          description: Filter by workstation ID
        - name: Enable
          in: query
          schema:
            type: integer
            enum:
              - 0
              - 1
          description: Filter by enable status
      responses:
        '200':
          description: List of equipment
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/EquipmentList'
    post:
      tags:
        - Equipment
      summary: Create equipment
      description: Create a new equipment entry
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - IEID
                - DepartmentID
                - Enable
                - EquipmentRole
              properties:
                IEID:
                  type: string
                  maxLength: 50
                DepartmentID:
                  type: integer
                InstrumentID:
                  type: string
                  maxLength: 150
                InstrumentName:
                  type: string
                  maxLength: 150
                WorkstationID:
                  type: integer
                Enable:
                  type: integer
                  enum:
                    - 0
                    - 1
                EquipmentRole:
                  type: string
                  maxLength: 1
      responses:
        '201':
          description: Equipment created
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: integer
    delete:
      tags:
        - Equipment
      summary: Delete equipment
      description: Soft delete an equipment entry
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - EID
              properties:
                EID:
                  type: integer
      responses:
        '200':
          description: Equipment deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
  /api/equipmentlist/{id}:
    get:
      tags:
        - Equipment
      summary: Get equipment by ID
      description: Get a single equipment entry by its EID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Equipment ID
      responses:
        '200':
          description: Equipment details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/EquipmentList'
    patch:
      tags:
        - Equipment
      summary: Update equipment
      description: Update an existing equipment entry
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Equipment ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                IEID:
                  type: string
                  maxLength: 50
                DepartmentID:
                  type: integer
                InstrumentID:
                  type: string
                  maxLength: 150
                InstrumentName:
                  type: string
                  maxLength: 150
                WorkstationID:
                  type: integer
                Enable:
                  type: integer
                  enum:
                    - 0
                    - 1
                EquipmentRole:
                  type: string
                  maxLength: 1
      responses:
        '200':
          description: Equipment updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: integer
  /api/location:
    get:
      tags:
        - Location
      summary: List locations
      security:
        - bearerAuth: []
      parameters:
        - name: LocCode
          in: query
          schema:
            type: string
          description: Filter by location code
        - name: LocName
          in: query
          schema:
            type: string
          description: Filter by location name (searches in LocFull)
      responses:
        '200':
          description: List of locations
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Location'
    post:
      tags:
        - Location
      summary: Create location
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - LocCode
                - LocFull
              properties:
                SiteID:
                  type: integer
                  description: Reference to site
                LocCode:
                  type: string
                  maxLength: 6
                  description: Location code (short identifier)
                Parent:
                  type: integer
                  nullable: true
                  description: Parent location ID for hierarchical locations
                LocFull:
                  type: string
                  maxLength: 255
                  description: Full location name
                Description:
                  type: string
                  maxLength: 255
                  description: Location description
                LocType:
                  type: string
                  description: Location type code (e.g., ROOM, WARD, BUILDING)
      responses:
        '201':
          description: Location created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      tags:
        - Location
      summary: Delete location
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - LocationID
              properties:
                LocationID:
                  type: integer
                  description: Location ID to delete
      responses:
        '200':
          description: Location deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
  /api/location/{id}:
    get:
      tags:
        - Location
      summary: Get location by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Location ID
      responses:
        '200':
          description: Location details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/Location'
    patch:
      tags:
        - Location
      summary: Update location
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Location ID to update
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                SiteID:
                  type: integer
                  description: Reference to site
                LocCode:
                  type: string
                  maxLength: 6
                  description: Location code (short identifier)
                Parent:
                  type: integer
                  nullable: true
                  description: Parent location ID for hierarchical locations
                LocFull:
                  type: string
                  maxLength: 255
                  description: Full location name
                Description:
                  type: string
                  maxLength: 255
                  description: Location description
                LocType:
                  type: string
                  description: Location type code (e.g., ROOM, WARD, BUILDING)
      responses:
        '201':
          description: Location updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/ordertest:
    get:
      tags:
        - Order
      summary: List orders
      security:
        - bearerAuth: []
      parameters:
        - name: page
          in: query
          schema:
            type: integer
        - name: perPage
          in: query
          schema:
            type: integer
        - name: InternalPID
          in: query
          schema:
            type: integer
          description: Filter by internal patient ID
        - name: OrderStatus
          in: query
          schema:
            type: string
            enum:
              - ORD
              - SCH
              - ANA
              - VER
              - REV
              - REP
          description: |
            ORD: Ordered
            SCH: Scheduled
            ANA: Analysis
            VER: Verified
            REV: Reviewed
            REP: Reported
      responses:
        '200':
          description: List of orders
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/OrderTestList'
    post:
      tags:
        - Order
      summary: Create order with specimens and tests
      description: Creates an order with associated specimens and patres records. Tests are grouped by container type to minimize specimen creation.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - InternalPID
                - Tests
              properties:
                OrderID:
                  type: string
                  description: Optional custom order ID (auto-generated if not provided)
                InternalPID:
                  type: integer
                  description: Patient internal ID
                PatVisitID:
                  type: integer
                  description: Visit ID
                SiteID:
                  type: integer
                  default: 1
                PlacerID:
                  type: string
                Priority:
                  type: string
                  enum:
                    - R
                    - S
                    - U
                  default: R
                  description: |
                    R: Routine
                    S: Stat
                    U: Urgent
                ReqApp:
                  type: string
                  description: Requesting application
                Comment:
                  type: string
                Tests:
                  type: array
                  items:
                    type: object
                    required:
                      - TestSiteID
                    properties:
                      TestSiteID:
                        type: integer
                        description: Test definition site ID
                      TestID:
                        type: integer
                        description: Alias for TestSiteID
      responses:
        '201':
          description: Order created successfully with specimens and tests
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/OrderTest'
        '400':
          description: Validation error
        '500':
          description: Server error
    delete:
      tags:
        - Order
      summary: Delete order
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - OrderID
              properties:
                OrderID:
                  type: string
      responses:
        '200':
          description: Order deleted
  /api/ordertest/status:
    post:
      tags:
        - Order
      summary: Update order status
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - OrderID
                - OrderStatus
              properties:
                OrderID:
                  type: string
                OrderStatus:
                  type: string
                  enum:
                    - ORD
                    - SCH
                    - ANA
                    - VER
                    - REV
                    - REP
                  description: |
                    ORD: Ordered
                    SCH: Scheduled
                    ANA: Analysis
                    VER: Verified
                    REV: Reviewed
                    REP: Reported
      responses:
        '200':
          description: Order status updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/OrderTest'
  /api/ordertest/{id}:
    get:
      tags:
        - Order
      summary: Get order by ID
      description: Returns order details with associated specimens and tests
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: Order ID (e.g., 0025030300001)
      responses:
        '200':
          description: Order details with specimens and tests
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/OrderTest'
    patch:
      tags:
        - Order
      summary: Update order
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: Order ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                Priority:
                  type: string
                  enum:
                    - R
                    - S
                    - U
                OrderStatus:
                  type: string
                  enum:
                    - ORD
                    - SCH
                    - ANA
                    - VER
                    - REV
                    - REP
                OrderingProvider:
                  type: string
                DepartmentID:
                  type: integer
                WorkstationID:
                  type: integer
      responses:
        '200':
          description: Order updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/OrderTest'
  /api/organization/account:
    get:
      tags:
        - Organization
      summary: List accounts
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of accounts
    post:
      tags:
        - Organization
      summary: Create account
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Account'
      responses:
        '201':
          description: Account created
    delete:
      tags:
        - Organization
      summary: Delete account
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - AccountID
              properties:
                AccountID:
                  type: integer
      responses:
        '200':
          description: Account deleted
  /api/organization/account/{id}:
    get:
      tags:
        - Organization
      summary: Get account by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Account details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Account'
    patch:
      tags:
        - Organization
      summary: Update account
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                AccountName:
                  type: string
                Parent:
                  type: integer
      responses:
        '200':
          description: Account updated
  /api/organization/site:
    get:
      tags:
        - Organization
      summary: List sites
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of sites
    post:
      tags:
        - Organization
      summary: Create site
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Site'
      responses:
        '201':
          description: Site created
    delete:
      tags:
        - Organization
      summary: Delete site
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - id
              properties:
                id:
                  type: integer
      responses:
        '200':
          description: Site deleted
  /api/organization/site/{id}:
    get:
      tags:
        - Organization
      summary: Get site by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Site details
    patch:
      tags:
        - Organization
      summary: Update site
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                SiteName:
                  type: string
                SiteCode:
                  type: string
                AccountID:
                  type: integer
      responses:
        '200':
          description: Site updated
  /api/organization/discipline:
    get:
      tags:
        - Organization
      summary: List disciplines
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of disciplines
    post:
      tags:
        - Organization
      summary: Create discipline
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Discipline'
      responses:
        '201':
          description: Discipline created
    delete:
      tags:
        - Organization
      summary: Delete discipline
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - id
              properties:
                id:
                  type: integer
      responses:
        '200':
          description: Discipline deleted
  /api/organization/discipline/{id}:
    get:
      tags:
        - Organization
      summary: Get discipline by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Discipline details
    patch:
      tags:
        - Organization
      summary: Update discipline
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                DisciplineName:
                  type: string
                DisciplineCode:
                  type: string
                SeqScr:
                  type: integer
                  description: Display order on screen
                SeqRpt:
                  type: integer
                  description: Display order in reports
      responses:
        '200':
          description: Discipline updated
  /api/organization/department:
    get:
      tags:
        - Organization
      summary: List departments
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of departments
    post:
      tags:
        - Organization
      summary: Create department
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Department'
      responses:
        '201':
          description: Department created
    delete:
      tags:
        - Organization
      summary: Delete department
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - id
              properties:
                id:
                  type: integer
      responses:
        '200':
          description: Department deleted
  /api/organization/department/{id}:
    get:
      tags:
        - Organization
      summary: Get department by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Department details
    patch:
      tags:
        - Organization
      summary: Update department
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                DeptName:
                  type: string
                DeptCode:
                  type: string
                SiteID:
                  type: integer
      responses:
        '200':
          description: Department updated
  /api/organization/workstation:
    get:
      tags:
        - Organization
      summary: List workstations
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of workstations
    post:
      tags:
        - Organization
      summary: Create workstation
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Workstation'
      responses:
        '201':
          description: Workstation created
    delete:
      tags:
        - Organization
      summary: Delete workstation
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - id
              properties:
                id:
                  type: integer
      responses:
        '200':
          description: Workstation deleted
  /api/organization/workstation/{id}:
    get:
      tags:
        - Organization
      summary: Get workstation by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Workstation details
    patch:
      tags:
        - Organization
      summary: Update workstation
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                WorkstationName:
                  type: string
                WorkstationCode:
                  type: string
                SiteID:
                  type: integer
                DepartmentID:
                  type: integer
      responses:
        '200':
          description: Workstation updated
  /api/organization/hostapp:
    get:
      tags:
        - Organization
      summary: List host applications
      security:
        - bearerAuth: []
      parameters:
        - name: HostAppID
          in: query
          schema:
            type: string
        - name: HostAppName
          in: query
          schema:
            type: string
      responses:
        '200':
          description: List of host applications
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/HostApp'
    post:
      tags:
        - Organization
      summary: Create host application
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HostApp'
      responses:
        '201':
          description: Host application created
    delete:
      tags:
        - Organization
      summary: Delete host application (soft delete)
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - HostAppID
              properties:
                HostAppID:
                  type: string
      responses:
        '200':
          description: Host application deleted
  /api/organization/hostapp/{id}:
    get:
      tags:
        - Organization
      summary: Get host application by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Host application details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HostApp'
    patch:
      tags:
        - Organization
      summary: Update host application
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                HostAppName:
                  type: string
                SiteID:
                  type: integer
      responses:
        '200':
          description: Host application updated
  /api/organization/hostcompara:
    get:
      tags:
        - Organization
      summary: List host communication parameters
      security:
        - bearerAuth: []
      parameters:
        - name: HostAppID
          in: query
          schema:
            type: string
        - name: HostIP
          in: query
          schema:
            type: string
      responses:
        '200':
          description: List of host communication parameters
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/HostComPara'
    post:
      tags:
        - Organization
      summary: Create host communication parameters
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HostComPara'
      responses:
        '201':
          description: Host communication parameters created
    delete:
      tags:
        - Organization
      summary: Delete host communication parameters (soft delete)
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - HostAppID
              properties:
                HostAppID:
                  type: string
      responses:
        '200':
          description: Host communication parameters deleted
  /api/organization/hostcompara/{id}:
    get:
      tags:
        - Organization
      summary: Get host communication parameters by HostAppID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Host communication parameters details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HostComPara'
    patch:
      tags:
        - Organization
      summary: Update host communication parameters
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                HostIP:
                  type: string
                HostPort:
                  type: string
                HostPwd:
                  type: string
      responses:
        '200':
          description: Host communication parameters updated
  /api/organization/codingsys:
    get:
      tags:
        - Organization
      summary: List coding systems
      security:
        - bearerAuth: []
      parameters:
        - name: CodingSysAbb
          in: query
          schema:
            type: string
        - name: FullText
          in: query
          schema:
            type: string
      responses:
        '200':
          description: List of coding systems
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/CodingSys'
    post:
      tags:
        - Organization
      summary: Create coding system
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CodingSys'
      responses:
        '201':
          description: Coding system created
    delete:
      tags:
        - Organization
      summary: Delete coding system (soft delete)
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - CodingSysID
              properties:
                CodingSysID:
                  type: integer
      responses:
        '200':
          description: Coding system deleted
  /api/organization/codingsys/{id}:
    get:
      tags:
        - Organization
      summary: Get coding system by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Coding system details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CodingSys'
    patch:
      tags:
        - Organization
      summary: Update coding system
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                CodingSysAbb:
                  type: string
                FullText:
                  type: string
                Description:
                  type: string
      responses:
        '200':
          description: Coding system updated
  /api/patvisit:
    get:
      tags:
        - Patient Visit
      summary: List patient visits
      security:
        - bearerAuth: []
      parameters:
        - name: InternalPID
          in: query
          schema:
            type: integer
          description: Filter by internal patient ID (exact match)
        - name: PVID
          in: query
          schema:
            type: string
          description: Filter by visit ID (partial match)
        - name: PatientID
          in: query
          schema:
            type: string
          description: Filter by patient ID (partial match)
        - name: PatientName
          in: query
          schema:
            type: string
          description: Search by patient name (searches in both first and last name)
        - name: CreateDateFrom
          in: query
          schema:
            type: string
            format: date-time
          description: Filter visits created on or after this date
        - name: CreateDateTo
          in: query
          schema:
            type: string
            format: date-time
          description: Filter visits created on or before this date
        - name: page
          in: query
          schema:
            type: integer
        - name: perPage
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: List of patient visits
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/PatientVisit'
                  total:
                    type: integer
                    description: Total number of records
                  page:
                    type: integer
                    description: Current page number
                  per_page:
                    type: integer
                    description: Number of records per page
    post:
      tags:
        - Patient Visit
      summary: Create patient visit
      description: |
        Creates a new patient visit. PVID is auto-generated with 'DV' prefix if not provided.
        Can optionally include PatDiag (diagnosis) and PatVisitADT (ADT information).
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - InternalPID
              properties:
                PVID:
                  type: string
                  description: Visit ID (auto-generated with DV prefix if not provided)
                InternalPID:
                  type: integer
                  description: Patient ID (required)
                EpisodeID:
                  type: string
                  description: Episode identifier
                SiteID:
                  type: integer
                  description: Site reference
                PatDiag:
                  type: object
                  description: Optional diagnosis information
                  properties:
                    DiagCode:
                      type: string
                    Diagnosis:
                      type: string
                PatVisitADT:
                  type: object
                  description: Optional ADT information
                  properties:
                    ADTCode:
                      type: string
                      enum:
                        - A01
                        - A02
                        - A03
                        - A04
                        - A08
                    LocationID:
                      type: integer
                    AttDoc:
                      type: integer
                    RefDoc:
                      type: integer
                    AdmDoc:
                      type: integer
                    CnsDoc:
                      type: integer
      responses:
        '201':
          description: Visit created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      PVID:
                        type: string
                      InternalPVID:
                        type: integer
    delete:
      tags:
        - Patient Visit
      summary: Delete patient visit
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Visit deleted successfully
  /api/patvisit/{id}:
    get:
      tags:
        - Patient Visit
      summary: Get visit by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: PVID (visit identifier like DV00001)
      responses:
        '200':
          description: Visit details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/PatientVisit'
    patch:
      tags:
        - Patient Visit
      summary: Update patient visit
      description: |
        Updates an existing patient visit. InternalPVID is required.
        Can update main visit data, PatDiag, and add new PatVisitADT records.
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Internal visit ID (InternalPVID)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                PVID:
                  type: string
                InternalPID:
                  type: integer
                EpisodeID:
                  type: string
                SiteID:
                  type: integer
                PatDiag:
                  type: object
                  description: Diagnosis information (will update if exists)
                  properties:
                    DiagCode:
                      type: string
                    Diagnosis:
                      type: string
                PatVisitADT:
                  type: array
                  description: Array of ADT records to add (new records only)
                  items:
                    type: object
                    properties:
                      ADTCode:
                        type: string
                        enum:
                          - A01
                          - A02
                          - A03
                          - A04
                          - A08
                      LocationID:
                        type: integer
                      AttDoc:
                        type: integer
                      RefDoc:
                        type: integer
                      AdmDoc:
                        type: integer
                      CnsDoc:
                        type: integer
                      sequence:
                        type: integer
                        description: Used for ordering multiple ADT records
      responses:
        '200':
          description: Visit updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      PVID:
                        type: string
                      InternalPVID:
                        type: integer
  /api/patvisit/patient/{patientId}:
    get:
      tags:
        - Patient Visit
      summary: Get visits by patient ID
      security:
        - bearerAuth: []
      parameters:
        - name: patientId
          in: path
          required: true
          schema:
            type: integer
          description: Internal Patient ID (InternalPID)
      responses:
        '200':
          description: Patient visits list
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/PatientVisit'
  /api/patvisitadt:
    post:
      tags:
        - Patient Visit
      summary: Create ADT record
      description: Create a new Admission/Discharge/Transfer record
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatVisitADT'
      responses:
        '201':
          description: ADT record created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
    delete:
      tags:
        - Patient Visit
      summary: Delete ADT visit (soft delete)
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - PVADTID
              properties:
                PVADTID:
                  type: integer
                  description: ADT record ID to delete
      responses:
        '200':
          description: ADT visit deleted successfully
  /api/patvisitadt/visit/{visitId}:
    get:
      tags:
        - Patient Visit
      summary: Get ADT history by visit ID
      description: Retrieve the complete Admission/Discharge/Transfer history for a visit, including all locations and doctors
      security:
        - bearerAuth: []
      parameters:
        - name: visitId
          in: path
          required: true
          schema:
            type: integer
          description: Internal Visit ID (InternalPVID)
      responses:
        '200':
          description: ADT history retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                    example: ADT history retrieved
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        PVADTID:
                          type: integer
                        InternalPVID:
                          type: integer
                        ADTCode:
                          type: string
                          enum:
                            - A01
                            - A02
                            - A03
                            - A04
                            - A08
                        LocationID:
                          type: integer
                        LocationName:
                          type: string
                        AttDoc:
                          type: integer
                        AttDocFirstName:
                          type: string
                        AttDocLastName:
                          type: string
                        RefDoc:
                          type: integer
                        RefDocFirstName:
                          type: string
                        RefDocLastName:
                          type: string
                        AdmDoc:
                          type: integer
                        AdmDocFirstName:
                          type: string
                        AdmDocLastName:
                          type: string
                        CnsDoc:
                          type: integer
                        CnsDocFirstName:
                          type: string
                        CnsDocLastName:
                          type: string
                        CreateDate:
                          type: string
                          format: date-time
                        EndDate:
                          type: string
                          format: date-time
  /api/patvisitadt/{id}:
    get:
      tags:
        - Patient Visit
      summary: Get ADT record by ID
      description: Retrieve a single ADT record by its ID, including location and doctor details
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: ADT record ID (PVADTID)
      responses:
        '200':
          description: ADT record retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                    example: ADT record retrieved
                  data:
                    type: object
                    properties:
                      PVADTID:
                        type: integer
                      InternalPVID:
                        type: integer
                      ADTCode:
                        type: string
                        enum:
                          - A01
                          - A02
                          - A03
                          - A04
                          - A08
                      LocationID:
                        type: integer
                      LocationName:
                        type: string
                      AttDoc:
                        type: integer
                      AttDocFirstName:
                        type: string
                      AttDocLastName:
                        type: string
                      RefDoc:
                        type: integer
                      RefDocFirstName:
                        type: string
                      RefDocLastName:
                        type: string
                      AdmDoc:
                        type: integer
                      AdmDocFirstName:
                        type: string
                      AdmDocLastName:
                        type: string
                      CnsDoc:
                        type: integer
                      CnsDocFirstName:
                        type: string
                      CnsDocLastName:
                        type: string
                      CreateDate:
                        type: string
                        format: date-time
                      EndDate:
                        type: string
                        format: date-time
    patch:
      tags:
        - Patient Visit
      summary: Update ADT record
      description: Update an existing ADT record
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: ADT record ID (PVADTID)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatVisitADT'
      responses:
        '200':
          description: ADT record updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
  /api/patient:
    get:
      tags:
        - Patient
      summary: List patients
      security:
        - bearerAuth: []
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: perPage
          in: query
          schema:
            type: integer
            default: 20
        - name: InternalPID
          in: query
          schema:
            type: integer
          description: Filter by internal patient ID
        - name: PatientID
          in: query
          schema:
            type: string
          description: Filter by patient ID
        - name: Name
          in: query
          schema:
            type: string
          description: Search by patient name
        - name: Birthdate
          in: query
          schema:
            type: string
            format: date
          description: Filter by birthdate (YYYY-MM-DD)
      responses:
        '200':
          description: List of patients
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PatientListResponse'
    post:
      tags:
        - Patient
      summary: Create new patient
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Patient'
      responses:
        '201':
          description: Patient created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      tags:
        - Patient
      summary: Delete patient (soft delete)
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - InternalPID
              properties:
                InternalPID:
                  type: integer
                  description: Internal patient record ID
      responses:
        '200':
          description: Patient deleted successfully
  /api/patient/check:
    get:
      tags:
        - Patient
      summary: Check if patient exists
      security:
        - bearerAuth: []
      parameters:
        - name: PatientID
          in: query
          schema:
            type: string
          description: Patient ID to check
        - name: EmailAddress
          in: query
          schema:
            type: string
            format: email
          description: Email address to check
        - name: Phone
          in: query
          schema:
            type: string
          description: Phone number to check
      responses:
        '200':
          description: Patient check result
          content:
            application/json:
              schema:
                type: object
                properties:
                  exists:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Patient'
  /api/patient/{id}:
    get:
      tags:
        - Patient
      summary: Get patient by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Internal patient record ID
      responses:
        '200':
          description: Patient details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    $ref: '#/components/schemas/Patient'
    patch:
      tags:
        - Patient
      summary: Partially update patient
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Internal patient record ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatientPatch'
      responses:
        '200':
          description: Patient updated successfully
        '400':
          description: Validation error
        '404':
          description: Patient not found
  /api/report/{orderID}:
    get:
      tags:
        - Report
      summary: Generate lab report
      description: Generate an HTML lab report for a specific order. Returns HTML content that can be viewed in browser or printed to PDF.
      security:
        - bearerAuth: []
      parameters:
        - name: orderID
          in: path
          required: true
          schema:
            type: integer
          description: Internal Order ID
      responses:
        '200':
          description: HTML lab report
          content:
            text/html:
              schema:
                type: string
                description: HTML content of the lab report
        '404':
          description: Order or patient not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Failed to generate report
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/result:
    get:
      tags:
        - Result
      summary: List results
      description: Retrieve patient test results with optional filters by order or patient
      security:
        - bearerAuth: []
      parameters:
        - name: order_id
          in: query
          schema:
            type: integer
          description: Filter by internal order ID
        - name: patient_id
          in: query
          schema:
            type: integer
          description: Filter by internal patient ID (returns cumulative results)
        - name: page
          in: query
          schema:
            type: integer
            default: 1
          description: Page number for pagination
        - name: per_page
          in: query
          schema:
            type: integer
            default: 20
          description: Number of results per page
      responses:
        '200':
          description: List of results
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        ResultID:
                          type: integer
                        OrderID:
                          type: integer
                        TestSiteID:
                          type: integer
                        TestSiteCode:
                          type: string
                        Result:
                          type: string
                          nullable: true
                        ResultDateTime:
                          type: string
                          format: date-time
                        RefNumID:
                          type: integer
                          nullable: true
                        RefTxtID:
                          type: integer
                          nullable: true
                        CreateDate:
                          type: string
                          format: date-time
                        TestSiteName:
                          type: string
                          nullable: true
                        Unit1:
                          type: string
                          nullable: true
                        Unit2:
                          type: string
                          nullable: true
                        Low:
                          type: number
                          nullable: true
                        High:
                          type: number
                          nullable: true
                        LowSign:
                          type: string
                          nullable: true
                        HighSign:
                          type: string
                          nullable: true
                        RefDisplay:
                          type: string
                          nullable: true
  /api/result/{id}:
    get:
      tags:
        - Result
      summary: Get result by ID
      description: Retrieve a specific result entry with all related data
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Result ID
      responses:
        '200':
          description: Result details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      ResultID:
                        type: integer
                      SiteID:
                        type: integer
                      OrderID:
                        type: integer
                      InternalSID:
                        type: integer
                      SID:
                        type: string
                      SampleID:
                        type: string
                      TestSiteID:
                        type: integer
                      TestSiteCode:
                        type: string
                      AspCnt:
                        type: integer
                      Result:
                        type: string
                        nullable: true
                      SampleType:
                        type: string
                        nullable: true
                      ResultDateTime:
                        type: string
                        format: date-time
                      WorkstationID:
                        type: integer
                        nullable: true
                      EquipmentID:
                        type: integer
                        nullable: true
                      RefNumID:
                        type: integer
                        nullable: true
                      RefTxtID:
                        type: integer
                        nullable: true
                      CreateDate:
                        type: string
                        format: date-time
                      TestSiteName:
                        type: string
                        nullable: true
                      Unit1:
                        type: string
                        nullable: true
                      Unit2:
                        type: string
                        nullable: true
                      Low:
                        type: number
                        nullable: true
                      High:
                        type: number
                        nullable: true
                      LowSign:
                        type: string
                        nullable: true
                      HighSign:
                        type: string
                        nullable: true
                      RefDisplay:
                        type: string
                        nullable: true
                      OrderNumber:
                        type: string
                        nullable: true
                      InternalPID:
                        type: integer
        '404':
          description: Result not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    patch:
      tags:
        - Result
      summary: Update result
      description: Update a result value with automatic validation against reference ranges. Returns calculated flag (L/H) in response but does not store it.
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Result ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                Result:
                  type: string
                  description: The result value
                RefNumID:
                  type: integer
                  description: Reference range ID to validate against
                SampleType:
                  type: string
                  nullable: true
                WorkstationID:
                  type: integer
                  nullable: true
                EquipmentID:
                  type: integer
                  nullable: true
      responses:
        '200':
          description: Result updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      result:
                        type: object
                      flag:
                        type: string
                        nullable: true
                        enum:
                          - L
                          - H
                        description: Calculated flag - L for Low, H for High, null for normal
        '400':
          description: Validation failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Result not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      tags:
        - Result
      summary: Delete result
      description: Soft delete a result entry by setting DelDate
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Result ID
      responses:
        '200':
          description: Result deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '404':
          description: Result not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/rule:
    get:
      tags:
        - Rule
      summary: List rules
      security:
        - bearerAuth: []
      parameters:
        - name: EventCode
          in: query
          schema:
            type: string
          description: Filter by event code
        - name: TestSiteID
          in: query
          schema:
            type: integer
          description: Filter by TestSiteID (returns rules linked to this test). Rules are only returned when attached to tests.
        - name: search
          in: query
          schema:
            type: string
          description: Search by rule code or name
      responses:
        '200':
          description: List of rules
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/RuleDef'
    post:
      tags:
        - Rule
      summary: Create rule
      description: |
        Create a new rule. Rules must be linked to at least one test via TestSiteIDs.
        A single rule can be linked to multiple tests. Rules are active only when attached to tests.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                RuleCode:
                  type: string
                  example: AUTO_SET_RESULT
                RuleName:
                  type: string
                  example: Automatically Set Result
                Description:
                  type: string
                EventCode:
                  type: string
                  example: test_created
                TestSiteIDs:
                  type: array
                  items:
                    type: integer
                  description: Array of TestSiteIDs to link this rule to (required)
                  example:
                    - 1
                    - 2
                    - 3
                ConditionExpr:
                  type: string
                  nullable: true
                  description: Raw DSL expression. Compile it first and persist the compiled JSON in ConditionExprCompiled.
                  example: if(sex('M'); result_set(0.5); result_set(0.6))
                ConditionExprCompiled:
                  type: string
                  nullable: true
                  description: Compiled JSON payload from POST /api/rule/compile
              required:
                - RuleCode
                - RuleName
                - EventCode
                - TestSiteIDs
      responses:
        '201':
          description: Rule created
  /api/rule/{id}:
    get:
      tags:
        - Rule
      summary: Get rule with linked tests
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: RuleID
      responses:
        '200':
          description: Rule details with linked test sites
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/RuleWithDetails'
        '404':
          description: Rule not found
    patch:
      tags:
        - Rule
      summary: Update rule
      description: |
        Update a rule. TestSiteIDs can be provided to update which tests the rule is linked to.
        Tests not in the new list will be unlinked, and new tests will be linked.
        Rules are active only when attached to tests.
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: RuleID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                RuleCode:
                  type: string
                RuleName:
                  type: string
                Description:
                  type: string
                EventCode:
                  type: string
                TestSiteIDs:
                  type: array
                  items:
                    type: integer
                  description: Array of TestSiteIDs to link this rule to
                ConditionExpr:
                  type: string
                  nullable: true
      responses:
        '200':
          description: Rule updated
        '404':
          description: Rule not found
    delete:
      tags:
        - Rule
      summary: Soft delete rule
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: RuleID
      responses:
        '200':
          description: Rule deleted
        '404':
          description: Rule not found
  /api/rule/validate:
    post:
      tags:
        - Rule
      summary: Validate/evaluate an expression
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                expr:
                  type: string
                context:
                  type: object
                  additionalProperties: true
              required:
                - expr
      responses:
        '200':
          description: Validation result
  /api/rule/compile:
    post:
      tags:
        - Rule
      summary: Compile DSL expression to engine-compatible structure
      description: |
        Compile a DSL expression to the engine-compatible JSON structure.
        Frontend calls this when user clicks "Compile" button.
        Returns compiled structure that can be saved to ConditionExprCompiled field.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                expr:
                  type: string
                  description: Raw DSL expression
                  example: if(sex('M'); result_set(0.5); result_set(0.6))
              required:
                - expr
      responses:
        '200':
          description: Compilation successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    type: object
                    properties:
                      raw:
                        type: string
                        description: Original DSL expression
                      compiled:
                        type: object
                        description: Parsed structure with conditionExpr, valueExpr, then, else
                      conditionExprCompiled:
                        type: string
                        description: JSON string to save to ConditionExprCompiled field
        '400':
          description: Compilation failed (invalid syntax)
  /api/specimen:
    get:
      tags:
        - Specimen
      summary: List specimens
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of specimens
    post:
      tags:
        - Specimen
      summary: Create specimen
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Specimen'
      responses:
        '201':
          description: Specimen created
  /api/specimen/{id}:
    get:
      tags:
        - Specimen
      summary: Get specimen by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Specimen details
    patch:
      tags:
        - Specimen
      summary: Update specimen
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Specimen ID (SID)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Specimen'
      responses:
        '200':
          description: Specimen updated
    delete:
      tags:
        - Specimen
      summary: Delete specimen (soft delete)
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Specimen ID (SID)
      responses:
        '200':
          description: Specimen deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                    example: Specimen deleted successfully
                  data:
                    type: object
                    properties:
                      SID:
                        type: integer
        '404':
          description: Specimen not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: failed
                  message:
                    type: string
                    example: Specimen not found
                  data:
                    type: null
        '500':
          description: Server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: failed
                  message:
                    type: string
                    example: Failed to delete specimen
                  data:
                    type: null
  /api/specimen/container:
    get:
      tags:
        - Specimen
      summary: List container definitions
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of container definitions
    post:
      tags:
        - Specimen
      summary: Create container definition
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContainerDef'
      responses:
        '201':
          description: Container definition created
  /api/specimen/container/{id}:
    get:
      tags:
        - Specimen
      summary: Get container definition by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Container definition details
    patch:
      tags:
        - Specimen
      summary: Update container definition
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Container definition ID (ConDefID)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContainerDef'
      responses:
        '200':
          description: Container definition updated
  /api/specimen/containerdef:
    get:
      tags:
        - Specimen
      summary: List container definitions (alias)
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of container definitions
    post:
      tags:
        - Specimen
      summary: Create container definition (alias)
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContainerDef'
      responses:
        '201':
          description: Container definition created
  /api/specimen/containerdef/{id}:
    patch:
      tags:
        - Specimen
      summary: Update container definition (alias)
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Container definition ID (ConDefID)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContainerDef'
      responses:
        '200':
          description: Container definition updated
  /api/specimen/prep:
    get:
      tags:
        - Specimen
      summary: List specimen preparations
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of specimen preparations
    post:
      tags:
        - Specimen
      summary: Create specimen preparation
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SpecimenPrep'
      responses:
        '201':
          description: Specimen preparation created
  /api/specimen/prep/{id}:
    get:
      tags:
        - Specimen
      summary: Get specimen preparation by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Specimen preparation details
    patch:
      tags:
        - Specimen
      summary: Update specimen preparation
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Specimen preparation ID (SpcPrpID)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SpecimenPrep'
      responses:
        '200':
          description: Specimen preparation updated
  /api/specimen/status:
    get:
      tags:
        - Specimen
      summary: List specimen statuses
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of specimen statuses
    post:
      tags:
        - Specimen
      summary: Create specimen status
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SpecimenStatus'
      responses:
        '201':
          description: Specimen status created
  /api/specimen/status/{id}:
    get:
      tags:
        - Specimen
      summary: Get specimen status by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Specimen status details
    patch:
      tags:
        - Specimen
      summary: Update specimen status
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Specimen status ID (SpcStaID)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SpecimenStatus'
      responses:
        '200':
          description: Specimen status updated
  /api/specimen/collection:
    get:
      tags:
        - Specimen
      summary: List specimen collection methods
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of collection methods
    post:
      tags:
        - Specimen
      summary: Create specimen collection method
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SpecimenCollection'
      responses:
        '201':
          description: Collection method created
  /api/specimen/collection/{id}:
    get:
      tags:
        - Specimen
      summary: Get specimen collection method by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Collection method details
    patch:
      tags:
        - Specimen
      summary: Update specimen collection method
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Specimen collection ID (SpcColID)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SpecimenCollection'
      responses:
        '200':
          description: Collection method updated
  /api/test/testmap:
    get:
      tags:
        - Test
      summary: List all test mappings
      security:
        - bearerAuth: []
      responses:
        '200':
          description: List of test mappings
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        TestMapID:
                          type: integer
                        HostType:
                          type: string
                        HostID:
                          type: string
                        HostName:
                          type: string
                        ClientType:
                          type: string
                        ClientID:
                          type: string
                        ClientName:
                          type: string
    post:
      tags:
        - Test
      summary: Create test mapping (header only)
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                HostType:
                  type: string
                  description: Host type code
                HostID:
                  type: string
                  description: Host identifier
                ClientType:
                  type: string
                  description: Client type code
                ClientID:
                  type: string
                  description: Client identifier
                details:
                  type: array
                  description: Optional detail records to create alongside the header
                  items:
                    type: object
                    properties:
                      HostTestCode:
                        type: string
                      HostTestName:
                        type: string
                      ConDefID:
                        type: integer
                      ClientTestCode:
                        type: string
                      ClientTestName:
                        type: string
      responses:
        '201':
          description: Test mapping created
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                  data:
                    type: integer
                    description: Created TestMapID
    delete:
      tags:
        - Test
      summary: Soft delete test mapping (cascades to details)
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                TestMapID:
                  type: integer
                  description: Test Map ID to delete (required)
              required:
                - TestMapID
      responses:
        '200':
          description: Test mapping deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                  data:
                    type: integer
                    description: Deleted TestMapID
        '404':
          description: Test mapping not found or already deleted
  /api/test/testmap/{id}:
    get:
      tags:
        - Test
      summary: Get test mapping by ID with details
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Test Map ID
      responses:
        '200':
          description: Test mapping details with nested detail records
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/TestMap'
        '404':
          description: Test mapping not found
    patch:
      tags:
        - Test
      summary: Update test mapping
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Test Map ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                HostType:
                  type: string
                HostID:
                  type: string
                ClientType:
                  type: string
                ClientID:
                  type: string
                details:
                  description: |
                    Detail payload supports either a flat array/object (treated as new rows)
                    or an operations object with `created`, `edited`, and `deleted` arrays.
                  oneOf:
                    - type: object
                      properties:
                        created:
                          type: array
                          description: New detail records to insert
                          items:
                            type: object
                            properties:
                              HostTestCode:
                                type: string
                              HostTestName:
                                type: string
                              ConDefID:
                                type: integer
                              ClientTestCode:
                                type: string
                              ClientTestName:
                                type: string
                        edited:
                          type: array
                          description: Existing detail records to update
                          items:
                            type: object
                            properties:
                              TestMapDetailID:
                                type: integer
                              HostTestCode:
                                type: string
                              HostTestName:
                                type: string
                              ConDefID:
                                type: integer
                              ClientTestCode:
                                type: string
                              ClientTestName:
                                type: string
                        deleted:
                          type: array
                          description: TestMapDetailIDs to soft delete
                          items:
                            type: integer
                    - type: array
                      description: Shortcut format for creating new details only
                      items:
                        type: object
                        properties:
                          HostTestCode:
                            type: string
                          HostTestName:
                            type: string
                          ConDefID:
                            type: integer
                          ClientTestCode:
                            type: string
                          ClientTestName:
                            type: string
                    - type: object
                      description: Shortcut format for creating a single new detail
                      properties:
                        HostTestCode:
                          type: string
                        HostTestName:
                          type: string
                        ConDefID:
                          type: integer
                        ClientTestCode:
                          type: string
                        ClientTestName:
                          type: string
      responses:
        '200':
          description: Test mapping updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                  data:
                    type: integer
                    description: Updated TestMapID
  /api/test/testmap/by-testcode/{testCode}:
    get:
      tags:
        - Test
      summary: Get test mappings by test code with details
      security:
        - bearerAuth: []
      parameters:
        - name: testCode
          in: path
          required: true
          schema:
            type: string
          description: Test Code (matches HostTestCode or ClientTestCode)
      responses:
        '200':
          description: List of test mappings with details for the test code
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/TestMap'
  /api/test/testmap/detail:
    get:
      tags:
        - Test
      summary: List test mapping details
      security:
        - bearerAuth: []
      parameters:
        - name: TestMapID
          in: query
          schema:
            type: integer
          description: Filter by TestMapID
      responses:
        '200':
          description: List of test mapping details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/TestMapDetail'
    post:
      tags:
        - Test
      summary: Create test mapping detail
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                TestMapID:
                  type: integer
                  description: Test Map ID (required)
                HostTestCode:
                  type: string
                HostTestName:
                  type: string
                ConDefID:
                  type: integer
                ClientTestCode:
                  type: string
                ClientTestName:
                  type: string
              required:
                - TestMapID
      responses:
        '201':
          description: Test mapping detail created
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: integer
                    description: Created TestMapDetailID
    delete:
      tags:
        - Test
      summary: Soft delete test mapping detail
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                TestMapDetailID:
                  type: integer
                  description: Test Map Detail ID to delete (required)
              required:
                - TestMapDetailID
      responses:
        '200':
          description: Test mapping detail deleted
  /api/test/testmap/detail/{id}:
    get:
      tags:
        - Test
      summary: Get test mapping detail by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Test Map Detail ID
      responses:
        '200':
          description: Test mapping detail
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/TestMapDetail'
    patch:
      tags:
        - Test
      summary: Update test mapping detail
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Test Map Detail ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                TestMapID:
                  type: integer
                HostTestCode:
                  type: string
                HostTestName:
                  type: string
                ConDefID:
                  type: integer
                ClientTestCode:
                  type: string
                ClientTestName:
                  type: string
      responses:
        '200':
          description: Test mapping detail updated
  /api/test/testmap/detail/by-testmap/{testMapID}:
    get:
      tags:
        - Test
      summary: Get test mapping details by test map ID
      security:
        - bearerAuth: []
      parameters:
        - name: testMapID
          in: path
          required: true
          schema:
            type: integer
          description: Test Map ID
      responses:
        '200':
          description: List of test mapping details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/TestMapDetail'
  /api/test/testmap/detail/batch:
    post:
      tags:
        - Test
      summary: Batch create test mapping details
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: object
                properties:
                  TestMapID:
                    type: integer
                  HostTestCode:
                    type: string
                  HostTestName:
                    type: string
                  ConDefID:
                    type: integer
                  ClientTestCode:
                    type: string
                  ClientTestName:
                    type: string
      responses:
        '200':
          description: Batch create results
    patch:
      tags:
        - Test
      summary: Batch update test mapping details
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: object
                properties:
                  TestMapDetailID:
                    type: integer
                  TestMapID:
                    type: integer
                  HostTestCode:
                    type: string
                  HostTestName:
                    type: string
                  ConDefID:
                    type: integer
                  ClientTestCode:
                    type: string
                  ClientTestName:
                    type: string
      responses:
        '200':
          description: Batch update results
    delete:
      tags:
        - Test
      summary: Batch delete test mapping details
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: integer
                description: TestMapDetailIDs to delete
      responses:
        '200':
          description: Batch delete results
  /api/test:
    get:
      tags:
        - Test
      summary: List test definitions
      security:
        - bearerAuth: []
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
          description: Page number for pagination
        - name: perPage
          in: query
          schema:
            type: integer
            default: 20
          description: Number of items per page
        - name: SiteID
          in: query
          schema:
            type: integer
          description: Filter by site ID
        - name: TestType
          in: query
          schema:
            type: string
            enum:
              - TEST
              - PARAM
              - CALC
              - GROUP
              - TITLE
          description: Filter by test type
        - name: isVisibleScr
          in: query
          schema:
            type: integer
            enum:
              - 0
              - 1
          description: Filter by screen visibility (0=hidden, 1=visible)
        - name: isVisibleRpt
          in: query
          schema:
            type: integer
            enum:
              - 0
              - 1
          description: Filter by report visibility (0=hidden, 1=visible)
        - name: search
          in: query
          schema:
            type: string
          description: Search by test code or name
      responses:
        '200':
          description: List of test definitions
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/TestDefinitionListItem'
                  pagination:
                    type: object
                    properties:
                      total:
                        type: integer
                        description: Total number of records matching the query
              examples:
                list_flat:
                  summary: Flat list response from testdefsite
                  value:
                    status: success
                    message: Data fetched successfully
                    data:
                      - TestSiteID: 21
                        TestSiteCode: GLU
                        TestSiteName: Glucose
                        TestType: TEST
                        SeqScr: 11
                        SeqRpt: 11
                        isVisibleScr: 1
                        isVisibleRpt: 1
                        isCountStat: 1
                        StartDate: '2026-01-01 00:00:00'
                        EndDate: null
                        DisciplineID: 2
                        DepartmentID: 2
                        DisciplineName: Clinical Chemistry
                        DepartmentName: Laboratory
                      - TestSiteID: 22
                        TestSiteCode: CREA
                        TestSiteName: Creatinine
                        TestType: TEST
                        SeqScr: 12
                        SeqRpt: 12
                        isVisibleScr: 1
                        isVisibleRpt: 1
                        isCountStat: 1
                        StartDate: '2026-01-01 00:00:00'
                        EndDate: null
                        DisciplineID: 2
                        DepartmentID: 2
                        DisciplineName: Clinical Chemistry
                        DepartmentName: Laboratory
    post:
      tags:
        - Test
      summary: Create test definition
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                SiteID:
                  type: integer
                  description: Site ID (required)
                TestSiteCode:
                  type: string
                  description: Test code (required)
                TestSiteName:
                  type: string
                  description: Test name (required)
                TestType:
                  type: string
                  enum:
                    - TEST
                    - PARAM
                    - CALC
                    - GROUP
                    - TITLE
                  description: Test type (required)
                Description:
                  type: string
                DisciplineID:
                  type: integer
                DepartmentID:
                  type: integer
                ResultType:
                  type: string
                  enum:
                    - NMRIC
                    - RANGE
                    - TEXT
                    - VSET
                    - NORES
                RefType:
                  type: string
                  enum:
                    - RANGE
                    - THOLD
                    - VSET
                    - TEXT
                    - NOREF
                VSet:
                  type: integer
                ReqQty:
                  type: number
                  format: decimal
                ReqQtyUnit:
                  type: string
                Unit1:
                  type: string
                Factor:
                  type: number
                  format: decimal
                Unit2:
                  type: string
                Decimal:
                  type: integer
                CollReq:
                  type: string
                Method:
                  type: string
                ExpectedTAT:
                  type: integer
                SeqScr:
                  type: integer
                SeqRpt:
                  type: integer
                IndentLeft:
                  type: integer
                FontStyle:
                  type: string
                isVisibleScr:
                  type: integer
                isVisibleRpt:
                  type: integer
                isCountStat:
                  type: integer
                testdefcal:
                  type: object
                  description: Calculated test metadata persisted in the `testdefcal` table.
                  properties:
                    FormulaCode:
                      type: string
                      description: Formula expression for calculated tests (e.g., "{TBIL} - {DBIL}")
                testdefgrp:
                  type: object
                  description: Group definition wrapper for CALC/GROUP member assignments.
                  properties:
                    members:
                      type: array
                      description: Array of member TestSiteIDs for CALC/GROUP definitions.
                      items:
                        type: object
                        properties:
                          TestSiteID:
                            type: integer
                            description: Foreign key referencing the member test's TestSiteID.
                        required:
                          - TestSiteID
                refnum:
                  type: array
                  items:
                    type: object
                reftxt:
                  type: array
                  items:
                    type: object
                testmap:
                  type: array
                  items:
                    type: object
                    properties:
                      HostType:
                        type: string
                      HostID:
                        type: string
                      HostTestCode:
                        type: string
                      HostTestName:
                        type: string
                      ClientType:
                        type: string
                      ClientID:
                        type: string
                      ClientTestCode:
                        type: string
                      ClientTestName:
                        type: string
                      ConDefID:
                        type: integer
                        nullable: true
              required:
                - SiteID
                - TestSiteCode
                - TestSiteName
                - TestType
            examples:
              TEST_no_ref:
                summary: Technical test without reference or map
                value:
                  SiteID: 1
                  TestSiteCode: TEST_NREF
                  TestSiteName: Numeric Test
                  TestType: TEST
                  SeqScr: 500
                  SeqRpt: 500
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 1
                  DisciplineID: 2
                  DepartmentID: 2
                  Unit1: mg/dL
                  Method: CBC Analyzer
              PARAM_no_ref:
                summary: Parameter without reference or map
                value:
                  SiteID: 1
                  TestSiteCode: PARAM_NRF
                  TestSiteName: Clinical Parameter
                  TestType: PARAM
                  SeqScr: 10
                  SeqRpt: 10
                  isVisibleScr: 1
                  isVisibleRpt: 0
                  isCountStat: 0
                  DisciplineID: 10
                  DepartmentID: 0
                  Unit1: cm
                  Method: Manual entry
              TEST_range_single:
                summary: Technical test with numeric range reference (single)
                value:
                  SiteID: 1
                  TestSiteCode: TEST_RANGE
                  TestSiteName: Glucose Range
                  TestType: TEST
                  SeqScr: 105
                  SeqRpt: 105
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 1
                  refnum:
                    - NumRefType: NMRC
                      RangeType: REF
                      Sex: '2'
                      LowSign: GE
                      Low: 70
                      HighSign: LE
                      High: 100
                      AgeStart: 6570
                      AgeEnd: 36135
                      Flag: 'N'
                  DisciplineID: 2
                  DepartmentID: 2
                  ResultType: NMRIC
                  RefType: RANGE
                  Unit1: mg/dL
                  Method: Hexokinase
              TEST_range_multiple_map:
                summary: Numeric reference with multiple ranges and test map
                value:
                  SiteID: 1
                  TestSiteCode: TEST_RMAP
                  TestSiteName: Glucose Panic Range
                  TestType: TEST
                  SeqScr: 110
                  SeqRpt: 110
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 1
                  refnum:
                    - NumRefType: NMRC
                      RangeType: REF
                      Sex: '2'
                      LowSign: GE
                      Low: 70
                      HighSign: LE
                      High: 100
                      AgeStart: 6570
                      AgeEnd: 36135
                      Flag: 'N'
                    - NumRefType: NMRC
                      RangeType: REF
                      Sex: '1'
                      LowSign: '>'
                      Low: 75
                      HighSign: <
                      High: 105
                      AgeStart: 6570
                      AgeEnd: 36135
                      Flag: 'N'
                  testmap:
                    - HostType: SITE
                      HostID: '1'
                      HostTestCode: GLU
                      HostTestName: Glucose
                      ClientType: WST
                      ClientID: '1'
                      ClientTestCode: GLU_C
                      ClientTestName: Glucose Client
                      ConDefID: 1
                    - HostType: SITE
                      HostID: '1'
                      HostTestCode: CREA
                      HostTestName: Creatinine
                      ClientType: WST
                      ClientID: '1'
                      ClientTestCode: CREA_C
                      ClientTestName: Creatinine Client
                      ConDefID: 2
                    - HostType: WST
                      HostID: '3'
                      HostTestCode: HB
                      HostTestName: Hemoglobin
                      ClientType: INST
                      ClientID: '2'
                      ClientTestCode: HB_C
                      ClientTestName: Hemoglobin Client
                      ConDefID: 3
                  DisciplineID: 2
                  DepartmentID: 2
                  ResultType: NMRIC
                  RefType: RANGE
                  Unit1: mg/dL
                  Method: Hexokinase
              TEST_threshold:
                summary: Technical test with threshold reference
                value:
                  SiteID: 1
                  TestSiteCode: TEST_THLD
                  TestSiteName: Sodium Threshold
                  TestType: TEST
                  SeqScr: 115
                  SeqRpt: 115
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 1
                  refnum:
                    - NumRefType: THOLD
                      RangeType: PANIC
                      Sex: '2'
                      LowSign: LT
                      Low: 120
                      AgeStart: 0
                      AgeEnd: 45625
                      Flag: H
                  DisciplineID: 2
                  DepartmentID: 2
                  ResultType: NMRIC
                  RefType: THOLD
                  Unit1: mmol/L
                  Method: Auto Analyzer
              TEST_threshold_map:
                summary: Threshold reference plus test map
                value:
                  SiteID: 1
                  TestSiteCode: TEST_TMAP
                  TestSiteName: Potassium Panic
                  TestType: TEST
                  SeqScr: 120
                  SeqRpt: 120
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 1
                  refnum:
                    - NumRefType: THOLD
                      RangeType: PANIC
                      Sex: '2'
                      LowSign: LT
                      Low: 120
                      AgeStart: 0
                      AgeEnd: 45625
                      Flag: H
                    - NumRefType: THOLD
                      RangeType: PANIC
                      Sex: '1'
                      LowSign: <
                      Low: 121
                      AgeStart: 0
                      AgeEnd: 45625
                      Flag: H
                  testmap:
                    - HostType: SITE
                      HostID: '1'
                      ClientType: WST
                      ClientID: '1'
                      details:
                        - HostTestCode: HB
                          HostTestName: Hemoglobin
                          ConDefID: 3
                          ClientTestCode: HB_C
                          ClientTestName: Hemoglobin Client
                        - HostTestCode: GLU
                          HostTestName: Glucose
                          ConDefID: 1
                          ClientTestCode: GLU_C
                          ClientTestName: Glucose Client
                  DisciplineID: 2
                  DepartmentID: 2
                  ResultType: NMRIC
                  RefType: THOLD
                  Unit1: mmol/L
                  Method: Auto Analyzer
              TEST_text:
                summary: Technical test with text reference
                value:
                  SiteID: 1
                  TestSiteCode: TEST_TEXT
                  TestSiteName: Disease Stage
                  TestType: TEST
                  SeqScr: 130
                  SeqRpt: 130
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 1
                  reftxt:
                    - SpcType: GEN
                      TxtRefType: TEXT
                      Sex: '2'
                      AgeStart: 6570
                      AgeEnd: 36135
                      RefTxt: NORM=Normal;HIGH=High
                      Flag: 'N'
                  DisciplineID: 1
                  DepartmentID: 1
                  ResultType: TEXT
                  RefType: TEXT
                  Method: Morphology
              TEST_text_map:
                summary: Text reference plus test map
                value:
                  SiteID: 1
                  TestSiteCode: TEST_TXM
                  TestSiteName: Disease Stage (Map)
                  TestType: TEST
                  SeqScr: 135
                  SeqRpt: 135
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 1
                  reftxt:
                    - SpcType: GEN
                      TxtRefType: TEXT
                      Sex: '2'
                      AgeStart: 6570
                      AgeEnd: 36135
                      RefTxt: NORM=Normal
                      Flag: 'N'
                    - SpcType: GEN
                      TxtRefType: TEXT
                      Sex: '1'
                      AgeStart: 6570
                      AgeEnd: 36135
                      RefTxt: ABN=Abnormal
                      Flag: 'N'
                  testmap:
                    - HostType: SITE
                      HostID: '1'
                      ClientType: WST
                      ClientID: '1'
                      details:
                        - HostTestCode: STAGE
                          HostTestName: Disease Stage
                          ConDefID: 4
                          ClientTestCode: STAGE_C
                          ClientTestName: Disease Stage Client
                  DisciplineID: 1
                  DepartmentID: 1
                  ResultType: TEXT
                  RefType: TEXT
              TEST_valueset:
                summary: Technical test using a value set result
                value:
                  SiteID: 1
                  TestSiteCode: TEST_VSET
                  TestSiteName: Urine Color
                  TestType: TEST
                  SeqScr: 140
                  SeqRpt: 140
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 1
                  reftxt:
                    - SpcType: GEN
                      TxtRefType: VSET
                      Sex: '2'
                      AgeStart: 0
                      AgeEnd: 43800
                      RefTxt: NORM=Normal;MACRO=Macro
                      Flag: 'N'
                  DisciplineID: 4
                  DepartmentID: 4
                  ResultType: VSET
                  RefType: VSET
                  Method: Visual
              TEST_valueset_map:
                summary: Value set reference with test map
                value:
                  SiteID: 1
                  TestSiteCode: TEST_VMAP
                  TestSiteName: Urine Color (Map)
                  TestType: TEST
                  SeqScr: 145
                  SeqRpt: 145
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 1
                  reftxt:
                    - SpcType: GEN
                      TxtRefType: VSET
                      Sex: '2'
                      AgeStart: 0
                      AgeEnd: 43800
                      RefTxt: NORM=Normal;ABN=Abnormal
                      Flag: 'N'
                  testmap:
                    - HostType: SITE
                      HostID: '1'
                      ClientType: WST
                      ClientID: '8'
                      details:
                        - HostTestCode: UCOLOR
                          HostTestName: Urine Color
                          ConDefID: 12
                          ClientTestCode: UCOLOR_C
                          ClientTestName: Urine Color Client
                  DisciplineID: 4
                  DepartmentID: 4
                  ResultType: VSET
                  RefType: VSET
              TEST_valueset_map_no_reftxt:
                summary: Value set result with mapping but without explicit text reference entries
                value:
                  SiteID: 1
                  TestSiteCode: TEST_VSETM
                  TestSiteName: Urine Result Map
                  TestType: TEST
                  SeqScr: 150
                  SeqRpt: 150
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 1
                  testmap:
                    - HostType: SITE
                      HostID: '1'
                      ClientType: WST
                      ClientID: '8'
                      details:
                        - HostTestCode: UGLUC
                          HostTestName: Urine Glucose
                          ConDefID: 12
                          ClientTestCode: UGLUC_C
                          ClientTestName: Urine Glucose Client
                  DisciplineID: 4
                  DepartmentID: 4
                  ResultType: VSET
                  RefType: VSET
              CALC_basic:
                summary: Calculated test with members (no references)
                value:
                  SiteID: 1
                  TestSiteCode: CALC_BASE
                  TestSiteName: Estimated GFR
                  TestType: CALC
                  SeqScr: 190
                  SeqRpt: 190
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 0
                  DisciplineID: 2
                  DepartmentID: 2
                  testdefcal:
                    FormulaCode: CKD_EPI(CREA,AGE,GENDER)
                  testdefgrp:
                    members:
                      - TestSiteID: 21
                      - TestSiteID: 22
              CALC_full:
                summary: Calculated test with numeric reference ranges and map
                value:
                  SiteID: 1
                  TestSiteCode: CALC_FULL
                  TestSiteName: Estimated GFR (Map)
                  TestType: CALC
                  SeqScr: 195
                  SeqRpt: 195
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 0
                  refnum:
                    - NumRefType: NMRC
                      RangeType: REF
                      Sex: '2'
                      LowSign: GE
                      Low: 10
                      HighSign: LE
                      High: 20
                      AgeStart: 6570
                      AgeEnd: 43800
                      Flag: 'N'
                  testmap:
                    - HostType: SITE
                      HostID: '1'
                      ClientType: WST
                      ClientID: '3'
                      details:
                        - HostTestCode: EGFR
                          HostTestName: eGFR
                          ConDefID: 1
                          ClientTestCode: EGFR_C
                          ClientTestName: eGFR Client
                  DisciplineID: 2
                  DepartmentID: 2
                  testdefcal:
                    FormulaCode: CKD_EPI(CREA,AGE,GENDER)
                  testdefgrp:
                    members:
                      - TestSiteID: 21
                      - TestSiteID: 22
              GROUP_with_members:
                summary: Group/profile test with members and mapping
                value:
                  SiteID: 1
                  TestSiteCode: GROUP_PNL
                  TestSiteName: Lipid Profile
                  TestType: GROUP
                  SeqScr: 10
                  SeqRpt: 10
                  isVisibleScr: 1
                  isVisibleRpt: 1
                  isCountStat: 1
                  testmap:
                    - HostType: SITE
                      HostID: '1'
                      ClientType: WST
                      ClientID: '3'
                      details:
                        - HostTestCode: LIPID
                          HostTestName: Lipid Profile
                          ConDefID: 1
                          ClientTestCode: LIPID_C
                          ClientTestName: Lipid Client
                  testdefgrp:
                    members:
                      - TestSiteID: 169
                      - TestSiteID: 170
      responses:
        '201':
          description: Test definition created
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: created
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      TestSiteId:
                        type: integer
        '400':
          description: Validation error (e.g., invalid member TestSiteID)
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: failed
                  message:
                    type: string
                    example: 'Invalid member TestSiteID(s): 185, 186. Make sure to use TestSiteID, not SeqScr or other values.'
  /api/test/{id}:
    get:
      tags:
        - Test
      summary: Get test definition by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Test Site ID
      responses:
        '200':
          description: Test definition details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/TestDefinition'
        '404':
          description: Test not found
    patch:
      tags:
        - Test
      summary: Update test definition
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Test Site ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                TestSiteID:
                  type: integer
                  description: Test Site ID (required)
                TestSiteCode:
                  type: string
                TestSiteName:
                  type: string
                TestType:
                  type: string
                  enum:
                    - TEST
                    - PARAM
                    - CALC
                    - GROUP
                    - TITLE
                Description:
                  type: string
                DisciplineID:
                  type: integer
                DepartmentID:
                  type: integer
                ResultType:
                  type: string
                  enum:
                    - NMRIC
                    - RANGE
                    - TEXT
                    - VSET
                    - NORES
                RefType:
                  type: string
                  enum:
                    - RANGE
                    - THOLD
                    - VSET
                    - TEXT
                    - NOREF
                VSet:
                  type: integer
                ReqQty:
                  type: number
                  format: decimal
                ReqQtyUnit:
                  type: string
                Unit1:
                  type: string
                Factor:
                  type: number
                  format: decimal
                Unit2:
                  type: string
                Decimal:
                  type: integer
                CollReq:
                  type: string
                Method:
                  type: string
                ExpectedTAT:
                  type: integer
                SeqScr:
                  type: integer
                SeqRpt:
                  type: integer
                IndentLeft:
                  type: integer
                FontStyle:
                  type: string
                isVisibleScr:
                  type: integer
                isVisibleRpt:
                  type: integer
                isCountStat:
                  type: integer
                testdefcal:
                  type: object
                  description: Calculated test metadata persisted in the `testdefcal` table.
                  properties:
                    FormulaCode:
                      type: string
                      description: Formula expression for calculated tests (e.g., "{TBIL} - {DBIL}")
                testdefgrp:
                  type: object
                  description: Group definition wrapper for CALC/GROUP member assignments.
                  properties:
                    members:
                      type: array
                      description: Array of member TestSiteIDs for CALC/GROUP definitions.
                      items:
                        type: object
                        properties:
                          TestSiteID:
                            type: integer
                            description: Foreign key referencing the member test's TestSiteID.
                        required:
                          - TestSiteID
                refnum:
                  type: array
                  items:
                    type: object
                reftxt:
                  type: array
                  items:
                    type: object
                testmap:
                  type: array
                  items:
                    type: object
                    properties:
                      HostType:
                        type: string
                      HostID:
                        type: string
                      HostTestCode:
                        type: string
                      HostTestName:
                        type: string
                      ClientType:
                        type: string
                      ClientID:
                        type: string
                      ClientTestCode:
                        type: string
                      ClientTestName:
                        type: string
                      ConDefID:
                        type: integer
                        nullable: true
              required:
                - TestSiteID
      responses:
        '200':
          description: Test definition updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      TestSiteId:
                        type: integer
        '400':
          description: Validation error (e.g., invalid member TestSiteID)
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: failed
                  message:
                    type: string
                    example: 'Invalid member TestSiteID(s): 185, 186. Make sure to use TestSiteID, not SeqScr or other values.'
    delete:
      tags:
        - Test
      summary: Soft delete test definition
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: Test Site ID to delete
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                TestSiteID:
                  type: integer
                  description: Optional - can be provided in body instead of path
      responses:
        '200':
          description: Test disabled successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      TestSiteId:
                        type: integer
                      EndDate:
                        type: string
                        format: date-time
        '404':
          description: Test not found
        '422':
          description: Test already disabled
  /api/user:
    get:
      tags:
        - User
      summary: List users with pagination and search
      security:
        - bearerAuth: []
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
          description: Page number
        - name: per_page
          in: query
          schema:
            type: integer
            default: 20
          description: Items per page
        - name: search
          in: query
          schema:
            type: string
          description: Search term for username, email, or name
      responses:
        '200':
          description: List of users with pagination
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                    example: Users retrieved successfully
                  data:
                    type: object
                    properties:
                      users:
                        type: array
                        items:
                          $ref: '#/components/schemas/User'
                      pagination:
                        type: object
                        properties:
                          current_page:
                            type: integer
                          per_page:
                            type: integer
                          total:
                            type: integer
                          total_pages:
                            type: integer
        '500':
          description: Server error
    post:
      tags:
        - User
      summary: Create new user
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserCreate'
      responses:
        '201':
          description: User created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                    example: User created successfully
                  data:
                    type: object
                    properties:
                      UserID:
                        type: integer
                      Username:
                        type: string
                      Email:
                        type: string
        '400':
          description: Validation failed
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: failed
                  message:
                    type: string
                    example: Validation failed
                  data:
                    type: object
        '500':
          description: Server error
  /api/user/{id}:
    get:
      tags:
        - User
      summary: Get user by ID
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: User ID
      responses:
        '200':
          description: User details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          description: User not found
        '500':
          description: Server error
    patch:
      tags:
        - User
      summary: Update existing user
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: User ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserUpdate'
      responses:
        '200':
          description: User updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                    example: User updated successfully
                  data:
                    type: object
                    properties:
                      UserID:
                        type: integer
                      updated_fields:
                        type: array
                        items:
                          type: string
        '400':
          description: UserID is required
        '404':
          description: User not found
        '500':
          description: Server error
    delete:
      tags:
        - User
      summary: Delete user (soft delete)
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          description: User ID
      responses:
        '200':
          description: User deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                    example: User deleted successfully
                  data:
                    type: object
                    properties:
                      UserID:
                        type: integer
        '404':
          description: User not found
        '500':
          description: Server error
  /api/valueset:
    get:
      tags:
        - ValueSet
      summary: List lib value sets
      description: List all library/system value sets from JSON files with item counts. Returns an array of objects with value, label, and count properties.
      security:
        - bearerAuth: []
      parameters:
        - name: search
          in: query
          schema:
            type: string
          description: Optional search term to filter value set names or labels
      responses:
        '200':
          description: List of lib value sets with item counts
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ValueSetListItem'
                    example:
                      - value: sex
                        label: Sex
                        count: 3
                      - value: marital_status
                        label: Marital Status
                        count: 6
                      - value: order_status
                        label: Order Status
                        count: 6
  /api/valueset/{key}:
    get:
      tags:
        - ValueSet
      summary: Get lib value set by key
      description: |
        Get a specific library/system value set from JSON files.

        **Available value set keys:**
        - `activity_result` - Activity Result
        - `additive` - Additive
        - `adt_event` - ADT Event
        - `area_class` - Area Class
        - `body_site` - Body Site
        - `collection_method` - Collection Method
        - `container_cap_color` - Container Cap Color
        - `container_class` - Container Class
        - `container_size` - Container Size
        - `country` - Country
        - `death_indicator` - Death Indicator
        - `did_type` - DID Type
        - `enable_disable` - Enable/Disable
        - `entity_type` - Entity Type
        - `ethnic` - Ethnic
        - `fasting_status` - Fasting Status
        - `formula_language` - Formula Language
        - `generate_by` - Generate By
        - `identifier_type` - Identifier Type
        - `location_type` - Location Type
        - `marital_status` - Marital Status
        - `math_sign` - Math Sign
        - `numeric_ref_type` - Numeric Reference Type
        - `operation` - Operation (CRUD)
        - `order_priority` - Order Priority
        - `order_status` - Order Status
        - `race` - Race (Ethnicity)
        - `range_type` - Range Type
        - `reference_type` - Reference Type
        - `religion` - Religion
        - `requested_entity` - Requested Entity
        - `result_type` - Result Type
        - `result_unit` - Result Unit
        - `sex` - Sex
        - `site_class` - Site Class
        - `site_type` - Site Type
        - `specimen_activity` - Specimen Activity
        - `specimen_condition` - Specimen Condition
        - `specimen_role` - Specimen Role
        - `specimen_status` - Specimen Status
        - `specimen_type` - Specimen Type
        - `test_activity` - Test Activity
        - `test_type` - Test Type
        - `text_ref_type` - Text Reference Type
        - `unit` - Unit
        - `v_category` - VCategory
        - `ws_type` - Workstation Type
      security:
        - bearerAuth: []
      parameters:
        - name: key
          in: path
          required: true
          schema:
            type: string
            enum:
              - activity_result
              - additive
              - adt_event
              - area_class
              - body_site
              - collection_method
              - container_cap_color
              - container_class
              - container_size
              - country
              - death_indicator
              - did_type
              - enable_disable
              - entity_type
              - ethnic
              - fasting_status
              - formula_language
              - generate_by
              - identifier_type
              - location_type
              - marital_status
              - math_sign
              - numeric_ref_type
              - operation
              - order_priority
              - order_status
              - race
              - range_type
              - reference_type
              - religion
              - requested_entity
              - result_type
              - result_unit
              - sex
              - site_class
              - site_type
              - specimen_activity
              - specimen_condition
              - specimen_role
              - specimen_status
              - specimen_type
              - test_activity
              - test_type
              - text_ref_type
              - unit
              - v_category
              - ws_type
          description: Value set key name
      responses:
        '200':
          description: Lib value set details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ValueSetLibItem'
  /api/valueset/refresh:
    post:
      tags:
        - ValueSet
      summary: Refresh lib ValueSet cache
      description: Clear and reload the library/system ValueSet cache from JSON files. Call this after modifying JSON files in app/Libraries/Data/.
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Lib ValueSet cache refreshed
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: success
                  message:
                    type: string
                    example: Cache cleared
  /api/valueset/user/items:
    get:
      tags:
        - ValueSet
      summary: List user value set items
      description: List value set items from database (user-defined)
      security:
        - bearerAuth: []
      parameters:
        - name: VSetID
          in: query
          schema:
            type: integer
          description: Filter by ValueSet ID
        - name: search
          in: query
          schema:
            type: string
          description: Search term to filter by VValue, VDesc, or VSName
        - name: param
          in: query
          schema:
            type: string
          description: Alternative search parameter (alias for search)
      responses:
        '200':
          description: List of user value set items
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ValueSetItem'
    post:
      tags:
        - ValueSet
      summary: Create user value set item
      description: Create value set item in database (user-defined)
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - VSetID
              properties:
                SiteID:
                  type: integer
                  description: Site reference (default 1)
                VSetID:
                  type: integer
                  description: Reference to value set definition (required)
                VOrder:
                  type: integer
                  description: Display order (default 0)
                VValue:
                  type: string
                  description: The value code
                VDesc:
                  type: string
                  description: The display description/label
      responses:
        '201':
          description: User value set item created
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/ValueSetItem'
  /api/valueset/user/items/{id}:
    get:
      tags:
        - ValueSet
      summary: Get user value set item by ID
      description: Get value set item from database (user-defined)
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: User value set item details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    $ref: '#/components/schemas/ValueSetItem'
    put:
      tags:
        - ValueSet
      summary: Update user value set item
      description: Update value set item in database (user-defined)
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                SiteID:
                  type: integer
                  description: Site reference
                VSetID:
                  type: integer
                  description: Reference to value set definition
                VOrder:
                  type: integer
                  description: Display order
                VValue:
                  type: string
                  description: The value code
                VDesc:
                  type: string
                  description: The display description/label
      responses:
        '200':
          description: User value set item updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/ValueSetItem'
    delete:
      tags:
        - ValueSet
      summary: Delete user value set item
      description: Delete value set item from database (user-defined)
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: User value set item deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
  /api/valueset/user/def:
    get:
      tags:
        - ValueSet
      summary: List user value set definitions
      description: List value set definitions from database (user-defined)
      security:
        - bearerAuth: []
      parameters:
        - name: search
          in: query
          schema:
            type: string
          description: Optional search term to filter definitions
        - name: page
          in: query
          schema:
            type: integer
            default: 1
          description: Page number for pagination
        - name: limit
          in: query
          schema:
            type: integer
            default: 100
          description: Number of items per page
      responses:
        '200':
          description: List of user value set definitions
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ValueSetDef'
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                      page:
                        type: integer
                      limit:
                        type: integer
    post:
      tags:
        - ValueSet
      summary: Create user value set definition
      description: Create value set definition in database (user-defined)
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                SiteID:
                  type: integer
                  description: Site reference (default 1)
                VSName:
                  type: string
                  description: Value set name
                VSDesc:
                  type: string
                  description: Value set description
      responses:
        '201':
          description: User value set definition created
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/ValueSetDef'
  /api/valueset/user/def/{id}:
    get:
      tags:
        - ValueSet
      summary: Get user value set definition by ID
      description: Get value set definition from database (user-defined)
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: User value set definition details
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    $ref: '#/components/schemas/ValueSetDef'
    put:
      tags:
        - ValueSet
      summary: Update user value set definition
      description: Update value set definition in database (user-defined)
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                SiteID:
                  type: integer
                  description: Site reference
                VSName:
                  type: string
                  description: Value set name
                VSDesc:
                  type: string
                  description: Value set description
      responses:
        '200':
          description: User value set definition updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    $ref: '#/components/schemas/ValueSetDef'
    delete:
      tags:
        - ValueSet
      summary: Delete user value set definition
      description: Delete value set definition from database (user-defined)
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: User value set definition deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT token from login endpoint
    cookieAuth:
      type: apiKey
      in: cookie
      name: token
      description: JWT token stored in HTTP-only cookie
  schemas:
    SuccessResponse:
      type: object
      properties:
        status:
          type: string
          example: success
        message:
          type: string
        code:
          type: integer
          example: 200
    ErrorResponse:
      type: object
      properties:
        status:
          type: string
          example: error
        message:
          type: string
        errors:
          type: object
    DashboardSummary:
      type: object
      properties:
        pendingOrders:
          type: integer
        todayResults:
          type: integer
        criticalResults:
          type: integer
        activePatients:
          type: integer
    LoginRequest:
      type: object
      required:
        - username
        - password
      properties:
        username:
          type: string
          example: labuser01
        password:
          type: string
          format: password
          example: secret123
    LoginResponse:
      type: object
      properties:
        status:
          type: string
          example: success
        code:
          type: integer
          example: 200
        message:
          type: string
          example: Login successful
    RegisterRequest:
      type: object
      required:
        - username
        - password
        - email
      properties:
        username:
          type: string
        password:
          type: string
          format: password
        email:
          type: string
          format: email
        full_name:
          type: string
    Patient:
      type: object
      required:
        - PatientID
        - Sex
        - NameFirst
        - Birthdate
      properties:
        PatientID:
          type: string
          maxLength: 30
          pattern: ^[A-Za-z0-9]+$
          description: Internal patient identifier
        AlternatePID:
          type: string
          maxLength: 30
          pattern: ^[A-Za-z0-9]+$
        Prefix:
          type: string
          maxLength: 10
          enum:
            - Mr
            - Mrs
            - Ms
            - Dr
            - Prof
        Sex:
          type: string
          enum:
            - '1'
            - '2'
          description: '1: Female, 2: Male'
        NameFirst:
          type: string
          minLength: 1
          maxLength: 60
          pattern: ^[A-Za-z'\. ]+$
        NameMiddle:
          type: string
          minLength: 1
          maxLength: 60
        NameMaiden:
          type: string
          minLength: 1
          maxLength: 60
        NameLast:
          type: string
          minLength: 1
          maxLength: 60
        Suffix:
          type: string
          maxLength: 10
        Birthdate:
          type: string
          format: date-time
          description: ISO 8601 UTC datetime
        PlaceOfBirth:
          type: string
          maxLength: 100
        Citizenship:
          type: string
          maxLength: 100
        Street_1:
          type: string
          maxLength: 255
        Street_2:
          type: string
          maxLength: 255
        Street_3:
          type: string
          maxLength: 255
        ZIP:
          type: string
          maxLength: 10
          pattern: ^[0-9]+$
        Phone:
          type: string
          pattern: ^\+?[0-9]{8,15}$
        MobilePhone:
          type: string
          pattern: ^\+?[0-9]{8,15}$
        EmailAddress1:
          type: string
          format: email
          maxLength: 100
        EmailAddress2:
          type: string
          format: email
          maxLength: 100
        PatIdt:
          $ref: '#/components/schemas/PatientIdentifier'
        LinkTo:
          type: array
          description: Array of linked patient references
          items:
            $ref: '#/components/schemas/LinkedPatient'
        Custodian:
          $ref: '#/components/schemas/Custodian'
        isDead:
          type: string
          enum:
            - '0'
            - '1'
          description: '0: No (alive), 1: Yes (deceased)'
        TimeOfDeath:
          type: string
          format: date-time
          description: ISO 8601 UTC datetime of death
        PatCom:
          type: string
          description: Patient comment/notes
        PatAtt:
          type: array
          description: Patient address entries
          items:
            $ref: '#/components/schemas/PatAttEntry'
        Province:
          type: integer
          description: Province AreaGeoID (foreign key to areageo table)
        ProvinceLabel:
          type: string
          description: Province name (resolved from areageo)
        City:
          type: integer
          description: City AreaGeoID (foreign key to areageo table)
        CityLabel:
          type: string
          description: City name (resolved from areageo)
        Country:
          type: string
          maxLength: 10
          description: Country ISO 3-letter code (e.g., IDN, USA)
        CountryLabel:
          type: string
          description: Country name (resolved from valueset)
        Race:
          type: string
          maxLength: 100
        MaritalStatus:
          type: string
          enum:
            - A
            - B
            - D
            - M
            - S
            - W
          description: 'A: Annulled, B: Separated, D: Divorced, M: Married, S: Single, W: Widowed'
        Religion:
          type: string
          maxLength: 100
        Ethnic:
          type: string
          maxLength: 100
    PatientIdentifier:
      type: object
      properties:
        IdentifierType:
          type: string
          enum:
            - KTP
            - PASS
            - SSN
            - SIM
            - KTAS
          description: |
            KTP: 16 digit numeric
            PASS: alphanumeric max 9
            SSN: 9 digit numeric
            SIM: 19-20 digit numeric
            KTAS: 11 digit numeric
        Identifier:
          type: string
          maxLength: 255
    LinkedPatient:
      type: object
      description: Linked patient reference
      properties:
        InternalPID:
          type: integer
          description: Internal patient ID of the linked patient
        PatientID:
          type: string
          description: Patient ID of the linked patient
    Custodian:
      type: object
      description: Patient custodian/guardian
      properties:
        InternalPID:
          type: integer
          description: Internal patient ID of the custodian
        PatientID:
          type: string
          description: Patient ID of the custodian
    PatAttEntry:
      type: object
      description: Patient address/attorney entry
      properties:
        Address:
          type: string
          description: Address text
    PatientListResponse:
      type: object
      properties:
        status:
          type: string
          example: success
        data:
          type: array
          items:
            $ref: '#/components/schemas/Patient'
        pagination:
          type: object
          properties:
            page:
              type: integer
            perPage:
              type: integer
            total:
              type: integer
    PatientVisit:
      type: object
      properties:
        InternalPVID:
          type: integer
          description: Primary key (auto-generated)
        PVID:
          type: string
          description: Visit ID (auto-generated with DV prefix if not provided)
        InternalPID:
          type: integer
          description: Reference to patient
        EpisodeID:
          type: string
          description: Episode identifier
        SiteID:
          type: integer
          description: Site reference
        LastLocation:
          type: string
          description: Full name of the last/current location from patvisitadt
        CreateDate:
          type: string
          format: date-time
        EndDate:
          type: string
          format: date-time
        ArchivedDate:
          type: string
          format: date-time
        DelDate:
          type: string
          format: date-time
        PatDiag:
          type: object
          description: Diagnosis information (optional)
          properties:
            DiagCode:
              type: string
            Diagnosis:
              type: string
        PatVisitADT:
          type: object
          description: ADT (Admission/Discharge/Transfer) information (optional)
          properties:
            ADTCode:
              type: string
              enum:
                - A01
                - A02
                - A03
                - A04
                - A08
            LocationID:
              type: integer
            AttDoc:
              type: integer
              description: Attending physician ContactID
            RefDoc:
              type: integer
              description: Referring physician ContactID
            AdmDoc:
              type: integer
              description: Admitting physician ContactID
            CnsDoc:
              type: integer
              description: Consulting physician ContactID
    PatVisitADT:
      type: object
      properties:
        PVADTID:
          type: integer
          description: Primary key (auto-generated)
        InternalPVID:
          type: integer
          description: Reference to patient visit
        ADTCode:
          type: string
          enum:
            - A01
            - A02
            - A03
            - A04
            - A08
          description: |
            A01: Admit
            A02: Transfer
            A03: Discharge
            A04: Register
            A08: Update
        LocationID:
          type: integer
          description: Location/ward reference
        AttDoc:
          type: integer
          description: Attending physician ContactID
        RefDoc:
          type: integer
          description: Referring physician ContactID
        AdmDoc:
          type: integer
          description: Admitting physician ContactID
        CnsDoc:
          type: integer
          description: Consulting physician ContactID
        CreateDate:
          type: string
          format: date-time
        EndDate:
          type: string
          format: date-time
        ArchivedDate:
          type: string
          format: date-time
        DelDate:
          type: string
          format: date-time
    Account:
      type: object
      properties:
        id:
          type: integer
        AccountName:
          type: string
        AccountCode:
          type: string
        AccountType:
          type: string
    Site:
      type: object
      properties:
        id:
          type: integer
        SiteName:
          type: string
        SiteCode:
          type: string
          maxLength: 2
          pattern: ^[A-Z0-9]{2}$
        AccountID:
          type: integer
    Discipline:
      type: object
      properties:
        id:
          type: integer
        DisciplineName:
          type: string
        DisciplineCode:
          type: string
        SeqScr:
          type: integer
          description: Display order on screen
        SeqRpt:
          type: integer
          description: Display order in reports
    Department:
      type: object
      properties:
        id:
          type: integer
        DeptName:
          type: string
        DeptCode:
          type: string
        SiteID:
          type: integer
    Workstation:
      type: object
      properties:
        id:
          type: integer
        WorkstationName:
          type: string
        WorkstationCode:
          type: string
        SiteID:
          type: integer
        DepartmentID:
          type: integer
    HostApp:
      type: object
      properties:
        HostAppID:
          type: string
          maxLength: 5
        HostAppName:
          type: string
        SiteID:
          type: integer
        SiteName:
          type: string
        CreateDate:
          type: string
          format: date-time
        EndDate:
          type: string
          format: date-time
    HostComPara:
      type: object
      properties:
        HostAppID:
          type: string
          maxLength: 5
        HostAppName:
          type: string
        HostIP:
          type: string
          maxLength: 15
        HostPort:
          type: string
          maxLength: 6
        HostPwd:
          type: string
        CreateDate:
          type: string
          format: date-time
        EndDate:
          type: string
          format: date-time
    CodingSys:
      type: object
      properties:
        CodingSysID:
          type: integer
        CodingSysAbb:
          type: string
          maxLength: 6
        FullText:
          type: string
        Description:
          type: string
        CreateDate:
          type: string
          format: date-time
        EndDate:
          type: string
          format: date-time
    Specimen:
      type: object
      properties:
        id:
          type: integer
        SpecimenID:
          type: string
        PatientID:
          type: string
        SpecimenType:
          type: string
          description: Specimen type code
        SpecimenTypeLabel:
          type: string
          description: Specimen type display text
        CollectionDate:
          type: string
          format: date-time
        CollectionMethod:
          type: string
          description: Collection method code
        CollectionMethodLabel:
          type: string
          description: Collection method display text
        ContainerID:
          type: integer
        SpecimenStatus:
          type: string
          description: Specimen status code
        SpecimenStatusLabel:
          type: string
          description: Specimen status display text
        BodySite:
          type: string
          description: Body site code
        BodySiteLabel:
          type: string
          description: Body site display text
    ContainerDef:
      type: object
      properties:
        id:
          type: integer
        ContainerCode:
          type: string
        ContainerName:
          type: string
        ConCategory:
          type: string
          description: Container category code
        ConCategoryLabel:
          type: string
          description: Container category display text
        ConSize:
          type: string
          description: Container size code
        ConSizeLabel:
          type: string
          description: Container size display text
        CapColor:
          type: string
          description: Cap color code
        CapColorLabel:
          type: string
          description: Cap color display text
    SpecimenPrep:
      type: object
      properties:
        id:
          type: integer
        PrepCode:
          type: string
        PrepName:
          type: string
        Description:
          type: string
    SpecimenStatus:
      type: object
      properties:
        id:
          type: integer
        StatusCode:
          type: string
        StatusName:
          type: string
        Description:
          type: string
        Status:
          type: string
          description: Status code
        StatusLabel:
          type: string
          description: Status display text
        Activity:
          type: string
          description: Activity code
        ActivityLabel:
          type: string
          description: Activity display text
    SpecimenCollection:
      type: object
      properties:
        id:
          type: integer
        CollectionCode:
          type: string
        CollectionName:
          type: string
        Description:
          type: string
        CollectionMethod:
          type: string
          description: Collection method code
        CollectionMethodLabel:
          type: string
          description: Collection method display text
        Additive:
          type: string
          description: Additive code
        AdditiveLabel:
          type: string
          description: Additive display text
        SpecimenRole:
          type: string
          description: Specimen role code
        SpecimenRoleLabel:
          type: string
          description: Specimen role display text
    TestDefinition:
      type: object
      properties:
        TestSiteID:
          type: integer
        SiteID:
          type: integer
        TestSiteCode:
          type: string
        TestSiteName:
          type: string
        TestType:
          type: string
          enum:
            - TEST
            - PARAM
            - CALC
            - GROUP
            - TITLE
          description: |
            TEST: Technical test
            PARAM: Parameter
            CALC: Calculated
            GROUP: Panel/Profile
            TITLE: Section header
        Description:
          type: string
        DisciplineID:
          type: integer
        DisciplineName:
          type: string
        DepartmentID:
          type: integer
        DepartmentName:
          type: string
        ResultType:
          type: string
          enum:
            - NMRIC
            - RANGE
            - TEXT
            - VSET
            - NORES
          description: |
            Result type determines the format of test results:
            - NMRIC: Single numeric value
            - RANGE: Numeric range (min-max)
            - TEXT: Free text result
            - VSET: Value set/enum result
            - NORES: No result (for GROUP and TITLE types)

            TestType to ResultType mapping:
            - TEST: NMRIC | RANGE | TEXT | VSET
            - PARAM: NMRIC | RANGE | TEXT | VSET
            - CALC: NMRIC (calculated result is always numeric)
            - GROUP: NORES (no result, container only)
            - TITLE: NORES (no result, header only)
        RefType:
          type: string
          enum:
            - RANGE
            - THOLD
            - VSET
            - TEXT
            - NOREF
          description: |
            Reference type determines which reference range table to use:
            - RANGE: Numeric reference range
            - THOLD: Threshold/panic range
            - VSET: Value set reference
            - TEXT: Free text reference
            - NOREF: No reference (for NORES result type)

            ResultType to RefType mapping:
            - NMRIC: RANGE | THOLD → refnum table
            - RANGE: RANGE | THOLD → refnum table
            - VSET: VSET → reftxt table
            - TEXT: TEXT → reftxt table
            - NORES: NOREF → (no reference table)
        VSet:
          type: integer
          description: Value set ID for VSET result type
        ReqQty:
          type: number
          format: decimal
          description: Required sample quantity
        ReqQtyUnit:
          type: string
          description: Unit for required quantity
        Unit1:
          type: string
          description: Primary unit
        Factor:
          type: number
          format: decimal
          description: Conversion factor
        Unit2:
          type: string
          description: Secondary unit (after conversion)
        Decimal:
          type: integer
          description: Number of decimal places
        CollReq:
          type: string
          description: Collection requirements
        Method:
          type: string
          description: Test method
        ExpectedTAT:
          type: integer
          description: Expected turnaround time
        SeqScr:
          type: integer
          description: Screen sequence
        SeqRpt:
          type: integer
          description: Report sequence
        IndentLeft:
          type: integer
          default: 0
        FontStyle:
          type: string
        isVisibleScr:
          type: integer
          default: 1
          description: Screen visibility (0=hidden, 1=visible)
        isVisibleRpt:
          type: integer
          default: 1
          description: Report visibility (0=hidden, 1=visible)
        isCountStat:
          type: integer
          default: 1
        Level:
          type: integer
        isRequestable:
          type: integer
          default: 1
          description: Flag indicating if test can be requested (1=yes, 0=no)
        CreateDate:
          type: string
          format: date-time
        StartDate:
          type: string
          format: date-time
        EndDate:
          type: string
          format: date-time
        FormulaCode:
          type: string
          description: Formula expression for calculated tests
        testdefcal:
          type: array
          description: Calculated test details (only for CALC type)
          items:
            type: object
        testdefgrp:
          type: object
          description: Group definition payload for GROUP and CALC types.
          properties:
            members:
              type: array
              description: |
                Group members (for GROUP and CALC types).
                When creating or updating, provide members in testdefgrp.members with TestSiteID field.
                Do NOT use Member, SeqScr, or Members fields when creating/updating.
              items:
                type: object
                properties:
                  TestGrpID:
                    type: integer
                    description: Group membership record ID
                  TestSiteID:
                    type: integer
                    description: Parent group TestSiteID
                  Member:
                    type: integer
                    description: |
                      Member TestSiteID (foreign key to testdefsite).
                      **Note**: This field is in the response. When creating/updating, use TestSiteID in testdefgrp.members instead.
                  TestSiteCode:
                    type: string
                    description: Member test code
                  TestSiteName:
                    type: string
                    description: Member test name
                  TestType:
                    type: string
                    description: Member test type
                  CreateDate:
                    type: string
                    format: date-time
                  EndDate:
                    type: string
                    format: date-time
        testmap:
          type: array
          description: Flat test mapping payload for /api/test create/update
          items:
            type: object
            properties:
              HostType:
                type: string
              HostID:
                type: string
              HostTestCode:
                type: string
              HostTestName:
                type: string
              ClientType:
                type: string
              ClientID:
                type: string
              ClientTestCode:
                type: string
              ClientTestName:
                type: string
              ConDefID:
                type: integer
                nullable: true
        refnum:
          type: array
          description: Numeric reference ranges (optional). Mutually exclusive with reftxt - a test can only have ONE reference type.
          items:
            type: object
            properties:
              RefNumID:
                type: integer
              NumRefType:
                type: string
                enum:
                  - NMRC
                  - THOLD
                description: NMRC=Numeric range, THOLD=Threshold
              NumRefTypeLabel:
                type: string
              RangeType:
                type: string
              RangeTypeLabel:
                type: string
              SpcType:
                type: string
                description: Specimen type code (e.g., GEN, EDTA)
              Sex:
                type: string
              SexLabel:
                type: string
              LowSign:
                type: string
              LowSignLabel:
                type: string
              HighSign:
                type: string
              HighSignLabel:
                type: string
              High:
                type: number
                format: float
              Low:
                type: number
                format: float
              AgeStart:
                type: integer
                description: Minimum patient age in days
              AgeEnd:
                type: integer
                description: Maximum patient age in days
              Flag:
                type: string
              Interpretation:
                type: string
              Notes:
                type: string
                description: Optional note attached to the numeric reference range
        reftxt:
          type: array
          description: Text reference ranges (optional). Mutually exclusive with refnum - a test can only have ONE reference type.
          items:
            type: object
            properties:
              RefTxtID:
                type: integer
              TxtRefType:
                type: string
                enum:
                  - TEXT
                  - VSET
                description: TEXT=Free text, VSET=Value set
              TxtRefTypeLabel:
                type: string
              Sex:
                type: string
              SexLabel:
                type: string
              AgeStart:
                type: integer
                description: Minimum patient age in days
              AgeEnd:
                type: integer
                description: Maximum patient age in days
              RefTxt:
                type: string
              Flag:
                type: string
      examples:
        TEST_numeric:
          summary: Technical test with numeric reference
          value:
            TestSiteID: 1
            SiteID: 1
            TestSiteCode: GLU
            TestSiteName: Glucose
            TestType: TEST
            DisciplineID: 2
            DepartmentID: 2
            ResultType: NMRIC
            RefType: NMRC
            Unit1: mg/dL
            ReqQty: 300
            ReqQtyUnit: uL
            Decimal: 0
            Method: Hexokinase
            SeqScr: 11
            SeqRpt: 11
            isVisibleScr: 1
            isVisibleRpt: 1
            isCountStat: 1
            refnum:
              - RefNumID: 1
                NumRefType: NMRC
                NumRefTypeLabel: Numeric
                RangeType: REF
                RangeTypeLabel: Reference Range
                Sex: '2'
                SexLabel: Male
                LowSign: GE
                LowSignLabel: '>='
                HighSign: LE
                HighSignLabel: <=
                Low: 70
                High: 100
                AgeStart: 6570
                AgeEnd: 36135
                Flag: 'N'
                Interpretation: Normal
        TEST_threshold:
          summary: Technical test with threshold reference (panic)
          value:
            TestSiteID: 2
            SiteID: 1
            TestSiteCode: GLU
            TestSiteName: Glucose
            TestType: TEST
            DisciplineID: 2
            DepartmentID: 2
            ResultType: NMRIC
            RefType: THOLD
            Unit1: mg/dL
            Decimal: 0
            Method: Hexokinase
            SeqScr: 11
            SeqRpt: 11
            isVisibleScr: 1
            isVisibleRpt: 1
            isCountStat: 1
            refnum:
              - RefNumID: 2
                NumRefType: THOLD
                NumRefTypeLabel: Threshold
                RangeType: PANIC
                RangeTypeLabel: Panic Range
                Sex: '1'
                SexLabel: Female
                LowSign: LT
                LowSignLabel: <
                High: 40
                AgeStart: 0
                AgeEnd: 43800
                Flag: L
                Interpretation: Critical Low
        TEST_text:
          summary: Technical test with text reference
          value:
            TestSiteID: 3
            SiteID: 1
            TestSiteCode: STAGE
            TestSiteName: Disease Stage
            TestType: TEST
            DisciplineID: 1
            DepartmentID: 1
            ResultType: VSET
            RefType: TEXT
            SeqScr: 50
            SeqRpt: 50
            isVisibleScr: 1
            isVisibleRpt: 1
            isCountStat: 1
            reftxt:
              - RefTxtID: 1
                TxtRefType: TEXT
                TxtRefTypeLabel: Text
                Sex: '2'
                SexLabel: Male
                AgeStart: 6570
                AgeEnd: 36135
                RefTxt: NORM=Normal;HYPO=Hypochromic;MACRO=Macrocytic
                Flag: 'N'
        PARAM:
          summary: Parameter test
          value:
            TestSiteID: 4
            SiteID: 1
            TestSiteCode: HEIGHT
            TestSiteName: Height
            TestType: PARAM
            DisciplineID: 10
            ResultType: NMRIC
            Unit1: cm
            Decimal: 0
            SeqScr: 40
            SeqRpt: 40
            isVisibleScr: 1
            isVisibleRpt: 0
            isCountStat: 0
        CALC:
          summary: Calculated test with reference
          value:
            TestSiteID: 5
            SiteID: 1
            TestSiteCode: EGFR
            TestSiteName: eGFR
            TestType: CALC
            DisciplineID: 2
            DepartmentID: 2
            Unit1: mL/min/1.73m2
            Decimal: 0
            SeqScr: 20
            SeqRpt: 20
            isVisibleScr: 1
            isVisibleRpt: 1
            isCountStat: 0
            testdefcal:
              - TestCalID: 1
                DisciplineID: 2
                DepartmentID: 2
                FormulaCode: CKD_EPI(CREA,AGE,GENDER)
                Unit1: mL/min/1.73m2
                Decimal: 0
            testdefgrp:
              members:
                - TestSiteID: 21
                  TestSiteCode: CREA
                  TestSiteName: Creatinine
                  TestType: TEST
                - TestSiteID: 51
                  TestSiteCode: AGE
                  TestSiteName: Age
                  TestType: PARAM
            refnum:
              - RefNumID: 5
                NumRefType: NMRC
                NumRefTypeLabel: Numeric
                RangeType: REF
                RangeTypeLabel: Reference Range
                Sex: '1'
                SexLabel: Female
                LowSign: GE
                LowSignLabel: '>='
                HighSign: LE
                HighSignLabel: <=
                Low: 10
                High: 20
                AgeStart: 6570
                AgeEnd: 43800
                Flag: 'N'
                Interpretation: Normal
        GROUP:
          summary: Panel/Profile test
          value:
            TestSiteID: 6
            SiteID: 1
            TestSiteCode: LIPID
            TestSiteName: Lipid Panel
            TestType: GROUP
            DisciplineID: 2
            DepartmentID: 2
            SeqScr: 51
            SeqRpt: 51
            isVisibleScr: 1
            isVisibleRpt: 1
            isCountStat: 1
            testdefgrp:
              members:
                - TestGrpID: 1
                  TestSiteID: 6
                  Member: 100
                  MemberTestSiteID: 100
                  TestSiteCode: CHOL
                  TestSiteName: Total Cholesterol
                  TestType: TEST
                - TestGrpID: 2
                  TestSiteID: 6
                  Member: 101
                  MemberTestSiteID: 101
                  TestSiteCode: TG
                  TestSiteName: Triglycerides
                  TestType: TEST
        TITLE:
          summary: Section header
          value:
            TestSiteID: 7
            SiteID: 1
            TestSiteCode: CHEM_HEADER
            TestSiteName: '--- CHEMISTRY ---'
            TestType: TITLE
            DisciplineID: 2
            DepartmentID: 2
            SeqScr: 100
            SeqRpt: 100
            isVisibleScr: 1
            isVisibleRpt: 1
            isCountStat: 0
    TestMap:
      type: object
      properties:
        TestMapID:
          type: integer
        HostType:
          type: string
          description: Host type code (e.g., SITE, WORKSTATION, INSTRUMENT)
        HostID:
          type: string
          description: Host identifier
        ClientType:
          type: string
          description: Client type code (e.g., SITE, WORKSTATION, INSTRUMENT)
        ClientID:
          type: string
          description: Client identifier
        HostName:
          type: string
          description: Resolved host name (from view)
        ClientName:
          type: string
          description: Resolved client name (from view)
        details:
          type: array
          description: Test mapping detail records
          items:
            $ref: '#/components/schemas/TestMapDetail'
        CreateDate:
          type: string
          format: date-time
        EndDate:
          type: string
          format: date-time
          description: Soft delete timestamp
    OrderTestList:
      type: object
      properties:
        InternalOID:
          type: integer
          description: Internal order ID
        OrderID:
          type: string
          description: Order ID (e.g., 0025030300001)
        PlacerID:
          type: string
          nullable: true
        InternalPID:
          type: integer
          description: Patient internal ID
        SiteID:
          type: integer
        PVADTID:
          type: integer
          description: Visit ADT ID
        ReqApp:
          type: string
          nullable: true
        Priority:
          type: string
          enum:
            - R
            - S
            - U
          description: |
            R: Routine
            S: Stat
            U: Urgent
        PriorityLabel:
          type: string
          description: Priority display text
        TrnDate:
          type: string
          format: date-time
          description: Transaction/Order date
        EffDate:
          type: string
          format: date-time
          description: Effective date
        CreateDate:
          type: string
          format: date-time
        OrderStatus:
          type: string
          enum:
            - ORD
            - SCH
            - ANA
            - VER
            - REV
            - REP
          description: |
            ORD: Ordered
            SCH: Scheduled
            ANA: Analysis
            VER: Verified
            REV: Reviewed
            REP: Reported
        OrderStatusLabel:
          type: string
          description: Order status display text
    OrderTest:
      type: object
      properties:
        InternalOID:
          type: integer
          description: Internal order ID
        OrderID:
          type: string
          description: Order ID (e.g., 0025030300001)
        PlacerID:
          type: string
          nullable: true
        InternalPID:
          type: integer
          description: Patient internal ID
        SiteID:
          type: integer
        PVADTID:
          type: integer
          description: Visit ADT ID
        ReqApp:
          type: string
          nullable: true
        Priority:
          type: string
          enum:
            - R
            - S
            - U
          description: |
            R: Routine
            S: Stat
            U: Urgent
        PriorityLabel:
          type: string
          description: Priority display text
        TrnDate:
          type: string
          format: date-time
          description: Transaction/Order date
        EffDate:
          type: string
          format: date-time
          description: Effective date
        CreateDate:
          type: string
          format: date-time
        OrderStatus:
          type: string
          enum:
            - ORD
            - SCH
            - ANA
            - VER
            - REV
            - REP
          description: |
            ORD: Ordered
            SCH: Scheduled
            ANA: Analysis
            VER: Verified
            REV: Reviewed
            REP: Reported
        OrderStatusLabel:
          type: string
          description: Order status display text
        Specimens:
          type: array
          items:
            $ref: '#/components/schemas/OrderSpecimen'
          description: Associated specimens for this order
        Tests:
          type: array
          items:
            $ref: '#/components/schemas/OrderTestItem'
          description: Test results (patres) for this order
    OrderItem:
      type: object
      properties:
        id:
          type: integer
        OrderID:
          type: string
        TestID:
          type: integer
        SpecimenID:
          type: string
        Status:
          type: string
    EdgeResultRequest:
      type: object
      required:
        - sample_id
        - instrument_id
      properties:
        sample_id:
          type: string
          description: Sample barcode/identifier
        instrument_id:
          type: string
          description: Instrument identifier
        patient_id:
          type: string
          description: Patient identifier (optional)
        results:
          type: array
          items:
            type: object
            properties:
              test_code:
                type: string
              result_value:
                type: string
              unit:
                type: string
              flags:
                type: string
                enum:
                  - H
                  - L
                  - 'N'
                  - A
                description: H=High, L=Low, N=Normal, A=Abnormal
    EdgeResultResponse:
      type: object
      properties:
        status:
          type: string
          example: success
        message:
          type: string
          example: Result received and queued
        data:
          type: object
          properties:
            edge_res_id:
              type: integer
            sample_id:
              type: string
            instrument_id:
              type: string
    EdgeOrder:
      type: object
      properties:
        OrderID:
          type: string
        PatientID:
          type: string
        SampleID:
          type: string
        Tests:
          type: array
          items:
            type: object
            properties:
              TestCode:
                type: string
              TestName:
                type: string
              SpecimenType:
                type: string
        Priority:
          type: string
        DueDateTime:
          type: string
          format: date-time
    ValueSetLibItem:
      type: object
      description: Library/system value set item from JSON files
      properties:
        value:
          type: string
          description: The value/key code
        label:
          type: string
          description: The display label
    ValueSetDef:
      type: object
      description: User-defined value set definition (from database)
      properties:
        VSetID:
          type: integer
          description: Primary key
        SiteID:
          type: integer
          description: Site reference
        VSName:
          type: string
          description: Value set name
        VSDesc:
          type: string
          description: Value set description
        CreateDate:
          type: string
          format: date-time
          description: Creation timestamp
        EndDate:
          type: string
          format: date-time
          nullable: true
          description: Soft delete timestamp
        ItemCount:
          type: integer
          description: Number of items in this value set
    ValueSetItem:
      type: object
      description: User-defined value set item (from database)
      properties:
        VID:
          type: integer
          description: Primary key
        SiteID:
          type: integer
          description: Site reference
        VSetID:
          type: integer
          description: Reference to value set definition
        VOrder:
          type: integer
          description: Display order
        VValue:
          type: string
          description: The value code
        VDesc:
          type: string
          description: The display description/label
        VCategory:
          type: string
          description: Category code
        CreateDate:
          type: string
          format: date-time
          description: Creation timestamp
        EndDate:
          type: string
          format: date-time
          nullable: true
          description: Soft delete timestamp
        VSName:
          type: string
          description: Value set name (from joined definition)
    Location:
      type: object
      properties:
        LocationID:
          type: integer
          description: Primary key
        SiteID:
          type: integer
          description: Reference to site
        LocCode:
          type: string
          maxLength: 6
          description: Location code (short identifier)
        Parent:
          type: integer
          nullable: true
          description: Parent location ID for hierarchical locations
        LocFull:
          type: string
          maxLength: 255
          description: Full location name
        Description:
          type: string
          maxLength: 255
          description: Location description
        LocType:
          type: string
          description: Location type code (e.g., ROOM, WARD, BUILDING)
        CreateDate:
          type: string
          format: date-time
        EndDate:
          type: string
          format: date-time
          nullable: true
    EquipmentList:
      type: object
      properties:
        EID:
          type: integer
          description: Equipment ID (auto-increment)
        IEID:
          type: string
          maxLength: 50
          description: Internal Equipment ID
        DepartmentID:
          type: integer
          description: Reference to department
        InstrumentID:
          type: string
          maxLength: 150
          description: Instrument identifier
        InstrumentName:
          type: string
          maxLength: 150
          description: Instrument display name
        WorkstationID:
          type: integer
          description: Reference to workstation
        Enable:
          type: integer
          enum:
            - 0
            - 1
          description: Equipment status (0=disabled, 1=enabled)
        EquipmentRole:
          type: string
          maxLength: 1
          description: Equipment role code
        CreateDate:
          type: string
          format: date-time
          description: Creation timestamp
        EndDate:
          type: string
          format: date-time
          nullable: true
          description: Deletion timestamp (soft delete)
        DepartmentName:
          type: string
          description: Joined department name
        WorkstationName:
          type: string
          description: Joined workstation name
    User:
      type: object
      properties:
        UserID:
          type: integer
          description: Unique user identifier
        Username:
          type: string
          description: Unique login username
        Email:
          type: string
          format: email
          description: User email address
        Name:
          type: string
          description: Full name of the user
        Role:
          type: string
          description: User role (admin, technician, doctor, etc.)
        Department:
          type: string
          description: Department name
        IsActive:
          type: boolean
          description: Whether the user account is active
        CreatedAt:
          type: string
          format: date-time
          description: Creation timestamp
        UpdatedAt:
          type: string
          format: date-time
          description: Last update timestamp
        DelDate:
          type: string
          format: date-time
          nullable: true
          description: Soft delete timestamp (null if active)
    UserCreate:
      type: object
      required:
        - Username
        - Email
      properties:
        Username:
          type: string
          minLength: 3
          maxLength: 50
          description: Unique login username
        Email:
          type: string
          format: email
          maxLength: 100
          description: User email address
        Name:
          type: string
          description: Full name of the user
        Role:
          type: string
          description: User role
        Department:
          type: string
          description: Department name
        IsActive:
          type: boolean
          default: true
          description: Whether the user account is active
    UserUpdate:
      type: object
      required:
        - UserID
      properties:
        UserID:
          type: integer
          description: User ID to update
        Email:
          type: string
          format: email
          description: User email address
        Name:
          type: string
          description: Full name of the user
        Role:
          type: string
          description: User role
        Department:
          type: string
          description: Department name
        IsActive:
          type: boolean
          description: Whether the user account is active
    UserListResponse:
      type: object
      properties:
        status:
          type: string
          example: success
        message:
          type: string
          example: Users retrieved successfully
        data:
          type: object
          properties:
            users:
              type: array
              items:
                $ref: '#/components/schemas/User'
            pagination:
              type: object
              properties:
                current_page:
                  type: integer
                per_page:
                  type: integer
                total:
                  type: integer
                total_pages:
                  type: integer
    RuleDef:
      type: object
      properties:
        RuleID:
          type: integer
        RuleCode:
          type: string
          example: AUTO_SET_RESULT
        RuleName:
          type: string
          example: Automatically Set Result
        Description:
          type: string
          nullable: true
        EventCode:
          type: string
          example: ORDER_CREATED
        ConditionExpr:
          type: string
          nullable: true
          description: Raw DSL expression (editable)
          example: if(sex('M'); result_set(0.5); result_set(0.6))
        ConditionExprCompiled:
          type: string
          nullable: true
          description: Compiled JSON structure (auto-generated from ConditionExpr)
          example: '{"conditionExpr":"patient[\"Sex\"] == \"M\"","valueExpr":"(patient[\"Sex\"] == \"M\") ? 0.5 : 0.6","then":[{"type":"RESULT_SET","value":0.5,"valueExpr":"0.5"}],"else":[{"type":"RESULT_SET","value":0.6,"valueExpr":"0.6"}]}'
        CreateDate:
          type: string
          format: date-time
          nullable: true
        StartDate:
          type: string
          format: date-time
          nullable: true
        EndDate:
          type: string
          format: date-time
          nullable: true
    RuleWithDetails:
      allOf:
        - $ref: '#/components/schemas/RuleDef'
        - type: object
          properties:
            linkedTests:
              type: array
              items:
                type: integer
              description: Array of TestSiteIDs this rule is linked to. Rules are active only when attached to tests.
    TestRule:
      type: object
      description: Mapping between a rule and a test site (testrule table). Rules are active when linked via this table.
      properties:
        TestRuleID:
          type: integer
        RuleID:
          type: integer
        TestSiteID:
          type: integer
        CreateDate:
          type: string
          format: date-time
          nullable: true
        EndDate:
          type: string
          format: date-time
          nullable: true
    AuditLogEntry:
      type: object
      properties:
        LogPatientID:
          type: integer
          nullable: true
        LogOrderID:
          type: integer
          nullable: true
        LogMasterID:
          type: integer
          nullable: true
        LogSystemID:
          type: integer
          nullable: true
        TblName:
          type: string
        RecID:
          type: string
        FldName:
          type: string
          nullable: true
        FldValuePrev:
          type: string
          nullable: true
        FldValueNew:
          type: string
          nullable: true
        UserID:
          type: string
        SiteID:
          type: string
        DIDType:
          type: string
          nullable: true
        DID:
          type: string
          nullable: true
        MachineID:
          type: string
          nullable: true
        SessionID:
          type: string
        AppID:
          type: string
        ProcessID:
          type: string
          nullable: true
        WebPageID:
          type: string
          nullable: true
        EventID:
          type: string
        ActivityID:
          type: string
        Reason:
          type: string
          nullable: true
        LogDate:
          type: string
          format: date-time
        Context:
          type: string
        IpAddress:
          type: string
          nullable: true
    AuditLogListResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/AuditLogEntry'
        pagination:
          type: object
          properties:
            page:
              type: integer
            perPage:
              type: integer
            total:
              type: integer
          required:
            - page
            - perPage
            - total
      required:
        - data
        - pagination
    AuditLogsEnvelope:
      type: object
      properties:
        status:
          type: string
        message:
          type: string
        data:
          $ref: '#/components/schemas/AuditLogListResponse'
      required:
        - status
        - message
        - data
    AuditLogsErrorResponse:
      type: object
      properties:
        status:
          type: string
        message:
          type: string
        data:
          nullable: true
      required:
        - status
        - message
        - data
    Contact:
      type: object
      properties:
        ContactID:
          type: integer
          description: Primary key
        NameFirst:
          type: string
          description: First name (required)
        NameLast:
          type: string
          description: Last name
        Title:
          type: string
          description: Title (e.g., Dr, Mr, Mrs)
        Initial:
          type: string
          description: Middle initial
        Birthdate:
          type: string
          format: date-time
          description: Date of birth
        EmailAddress1:
          type: string
          format: email
          description: Primary email address
        EmailAddress2:
          type: string
          format: email
          description: Secondary email address
        Phone:
          type: string
          description: Primary phone number
        MobilePhone1:
          type: string
          description: Primary mobile number
        MobilePhone2:
          type: string
          description: Secondary mobile number
        Specialty:
          type: string
          description: Medical specialty code
        SubSpecialty:
          type: string
          description: Sub-specialty code
        CreateDate:
          type: string
          format: date-time
        EndDate:
          type: string
          format: date-time
          description: Occupation display text
    OrderSpecimen:
      type: object
      properties:
        InternalSID:
          type: integer
          description: Internal specimen ID
        SID:
          type: string
          description: Specimen ID (e.g., 0025030300001-S01)
        SiteID:
          type: integer
        OrderID:
          type: integer
          description: Reference to internal order ID
        ConDefID:
          type: integer
          description: Container Definition ID
          nullable: true
        ConCode:
          type: string
          description: Container code
          nullable: true
        ConName:
          type: string
          description: Container name
          nullable: true
        Qty:
          type: integer
          description: Quantity
        Unit:
          type: string
          description: Unit of measurement
        Status:
          type: string
          enum:
            - PENDING
            - COLLECTED
            - RECEIVED
            - PREPARED
            - REJECTED
          description: Current specimen status
        GenerateBy:
          type: string
          description: Source that generated this specimen
        CreateDate:
          type: string
          format: date-time
    OrderTestItem:
      type: object
      properties:
        ResultID:
          type: integer
          description: Unique result ID
        OrderID:
          type: integer
          description: Reference to internal order ID
        InternalSID:
          type: integer
          description: Reference to specimen
          nullable: true
        TestSiteID:
          type: integer
          description: Test definition site ID
        TestSiteCode:
          type: string
          description: Test code
        TestSiteName:
          type: string
          description: Test name
          nullable: true
        TestType:
          type: string
          description: Test type code identifying the test category
          enum:
            - TEST
            - PARAM
            - CALC
            - GROUP
            - TITLE
        SID:
          type: string
          description: Order ID reference
        SampleID:
          type: string
          description: Sample ID (same as OrderID)
        SeqScr:
          type: integer
          nullable: true
          description: Sequence number for this test on the screen
        SeqRpt:
          type: integer
          nullable: true
          description: Sequence number for this test in reports
        Result:
          type: string
          description: Test result value
          nullable: true
        Discipline:
          type: object
          description: Discipline metadata used for ordering tests
          properties:
            DisciplineID:
              type: integer
              nullable: true
            DisciplineCode:
              type: string
              nullable: true
            DisciplineName:
              type: string
              nullable: true
            SeqScr:
              type: integer
              nullable: true
              description: Discipline sequence on the screen
            SeqRpt:
              type: integer
              nullable: true
              description: Discipline sequence in reports
        ResultDateTime:
          type: string
          format: date-time
          description: Result timestamp
        CreateDate:
          type: string
          format: date-time
    PatientPatch:
      type: object
      description: |
        Partial patient update payload.
        Omitted fields are left unchanged. Send null explicitly to clear nullable fields.
      properties:
        PatientID:
          type: string
          maxLength: 30
          pattern: ^[A-Za-z0-9]+$
          description: Internal patient identifier
        AlternatePID:
          type: string
          maxLength: 30
          pattern: ^[A-Za-z0-9]+$
        Prefix:
          type: string
          maxLength: 10
          enum:
            - Mr
            - Mrs
            - Ms
            - Dr
            - Prof
        Sex:
          type: string
          enum:
            - '1'
            - '2'
          description: '1: Female, 2: Male'
        NameFirst:
          type: string
          minLength: 1
          maxLength: 60
          pattern: ^[A-Za-z'\. ]+$
        NameMiddle:
          type: string
          minLength: 1
          maxLength: 60
        NameMaiden:
          type: string
          minLength: 1
          maxLength: 60
        NameLast:
          type: string
          minLength: 1
          maxLength: 60
        Suffix:
          type: string
          maxLength: 10
        Birthdate:
          type: string
          format: date-time
          description: ISO 8601 UTC datetime
        PlaceOfBirth:
          type: string
          maxLength: 100
        Citizenship:
          type: string
          maxLength: 100
        Street_1:
          type: string
          maxLength: 255
        Street_2:
          type: string
          maxLength: 255
        Street_3:
          type: string
          maxLength: 255
        ZIP:
          type: string
          maxLength: 10
          pattern: ^[0-9]+$
        Phone:
          type: string
          pattern: ^\+?[0-9]{8,15}$
        MobilePhone:
          type: string
          pattern: ^\+?[0-9]{8,15}$
        EmailAddress1:
          type: string
          format: email
          maxLength: 100
        EmailAddress2:
          type: string
          format: email
          maxLength: 100
        PatIdt:
          allOf:
            - $ref: '#/components/schemas/PatientIdentifier'
          nullable: true
        LinkTo:
          type: array
          description: Array of linked patient references
          items:
            $ref: '#/components/schemas/LinkedPatient'
        Custodian:
          allOf:
            - $ref: '#/components/schemas/Custodian'
          nullable: true
        isDead:
          type: string
          enum:
            - '0'
            - '1'
          description: '0: No (alive), 1: Yes (deceased)'
        TimeOfDeath:
          type: string
          format: date-time
          description: ISO 8601 UTC datetime of death
        PatCom:
          type: string
          description: Patient comment/notes
          nullable: true
        PatAtt:
          type: array
          description: Patient address entries
          nullable: true
          items:
            $ref: '#/components/schemas/PatAttEntry'
        Province:
          type: integer
          description: Province AreaGeoID (foreign key to areageo table)
        City:
          type: integer
          description: City AreaGeoID (foreign key to areageo table)
        Country:
          type: string
          maxLength: 10
          description: Country ISO 3-letter code (e.g., IDN, USA)
        Race:
          type: string
          maxLength: 100
        MaritalStatus:
          type: string
          enum:
            - A
            - B
            - D
            - M
            - S
            - W
          description: 'A: Annulled, B: Separated, D: Divorced, M: Married, S: Single, W: Widowed'
        Religion:
          type: string
          maxLength: 100
        Ethnic:
          type: string
          maxLength: 100
    TestMapDetail:
      type: object
      properties:
        TestMapDetailID:
          type: integer
        TestMapID:
          type: integer
        HostTestCode:
          type: string
          description: Test code in host system
        HostTestName:
          type: string
          description: Test name in host system
        ConDefID:
          type: integer
          description: Container definition ID
        ClientTestCode:
          type: string
          description: Test code in client system
        ClientTestName:
          type: string
          description: Test name in client system
        CreateDate:
          type: string
          format: date-time
        EndDate:
          type: string
          format: date-time
          description: Soft delete timestamp
    TestDefinitionListItem:
      type: object
      properties:
        TestSiteID:
          type: integer
        TestSiteCode:
          type: string
        TestSiteName:
          type: string
        TestType:
          type: string
          enum:
            - TEST
            - PARAM
            - CALC
            - GROUP
            - TITLE
        SeqScr:
          type: integer
        SeqRpt:
          type: integer
        isVisibleScr:
          type: integer
          enum:
            - 0
            - 1
        isVisibleRpt:
          type: integer
          enum:
            - 0
            - 1
        isCountStat:
          type: integer
        StartDate:
          type: string
          format: date-time
        EndDate:
          type: string
          format: date-time
          nullable: true
        DisciplineID:
          type: integer
          nullable: true
        DepartmentID:
          type: integer
          nullable: true
        DisciplineName:
          type: string
          nullable: true
        DepartmentName:
          type: string
          nullable: true
    ValueSetListItem:
      type: object
      description: Library/system value set summary (from JSON files)
      properties:
        value:
          type: string
          description: The value set key/name
        label:
          type: string
          description: The display name/label
        count:
          type: integer
          description: Number of items in this value set
