From 9eef675a5212aac16490ba9bc3948e5f7c5c24f0 Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Thu, 26 Feb 2026 16:48:27 +0700 Subject: [PATCH] refactor(testmap): reorganize testmap docs and update components --- docs/api-docs.bundled.yaml | 5500 ----------------- docs/testmap.yaml | 503 ++ src/lib/api/testmap.js | 246 +- .../(app)/master-data/testmap/+page.svelte | 239 +- .../master-data/testmap/TestMapModal.svelte | 223 +- 5 files changed, 931 insertions(+), 5780 deletions(-) delete mode 100644 docs/api-docs.bundled.yaml create mode 100644 docs/testmap.yaml diff --git a/docs/api-docs.bundled.yaml b/docs/api-docs.bundled.yaml deleted file mode 100644 index 098ec39..0000000 --- a/docs/api-docs.bundled.yaml +++ /dev/null @@ -1,5500 +0,0 @@ -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: Patients - description: Patient registration and management - - name: Patient Visits - description: Patient visit/encounter management - - name: Organization - description: Organization structure (accounts, sites, disciplines, departments, workstations) - - name: Specimen - description: Specimen and container management - - name: Tests - description: Test definitions and test catalog - - name: Orders - description: Laboratory order management - - name: Results - description: Patient results reporting - - name: Edge API - description: Instrument integration endpoints - - name: Contacts - description: Contact management (doctors, practitioners, etc.) - - name: Locations - description: Location management (rooms, wards, buildings) - - name: ValueSets - description: Value set definitions and items - - name: Demo - description: Demo/test endpoints (no authentication) - - name: EquipmentList - description: Laboratory equipment and instrument management -paths: - /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/contact: - get: - tags: - - Contacts - 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: - - Contacts - 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' - patch: - tags: - - Contacts - summary: Update contact - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - ContactID - - NameFirst - properties: - ContactID: - type: integer - description: Contact ID to update - 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' - delete: - tags: - - Contacts - 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: - - Contacts - 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' - /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/results: - 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/orders: - 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/orders/{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: - - EquipmentList - 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: - - EquipmentList - 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 - patch: - tags: - - EquipmentList - summary: Update equipment - description: Update an existing equipment entry - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - EID - properties: - EID: - type: integer - 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 - delete: - tags: - - EquipmentList - 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: - - EquipmentList - 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' - /api/location: - get: - tags: - - Locations - 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: - - Locations - 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' - patch: - tags: - - Locations - summary: Update location - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - LocationID - properties: - LocationID: - type: integer - description: Location ID to update - 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' - delete: - tags: - - Locations - 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: - - Locations - 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' - /api/ordertest: - get: - tags: - - Orders - 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 - post: - tags: - - Orders - summary: Create order - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - PatientID - - Tests - properties: - PatientID: - type: string - VisitID: - type: string - Priority: - type: string - enum: - - R - - S - - U - description: | - R: Routine - S: Stat - U: Urgent - SiteID: - type: integer - RequestingPhysician: - type: string - Tests: - type: array - items: - type: object - properties: - TestID: - type: integer - SpecimenType: - type: string - responses: - '201': - description: Order created successfully - patch: - tags: - - Orders - summary: Update order - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/OrderTest' - responses: - '200': - description: Order updated - delete: - tags: - - Orders - summary: Delete order - security: - - bearerAuth: [] - responses: - '200': - description: Order deleted - /api/ordertest/status: - post: - tags: - - Orders - 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 - /api/ordertest/{id}: - get: - tags: - - Orders - summary: Get order by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '200': - description: Order details - /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' - /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 - patch: - tags: - - Organization - summary: Update site - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - SiteName: - type: string - SiteCode: - type: string - AccountID: - type: integer - responses: - '200': - description: Site updated - 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 - /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 - patch: - tags: - - Organization - summary: Update discipline - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - DisciplineName: - type: string - DisciplineCode: - type: string - responses: - '200': - description: Discipline updated - 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 - /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 - patch: - tags: - - Organization - summary: Update department - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - DeptName: - type: string - DeptCode: - type: string - SiteID: - type: integer - responses: - '200': - description: Department updated - 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 - /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 - patch: - tags: - - Organization - summary: Update workstation - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - WorkstationName: - type: string - WorkstationCode: - type: string - SiteID: - type: integer - DepartmentID: - type: integer - responses: - '200': - description: Workstation updated - 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 - /api/patvisit: - get: - tags: - - Patient Visits - summary: List patient visits - security: - - bearerAuth: [] - parameters: - - 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 Visits - 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 - patch: - tags: - - Patient Visits - 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: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - InternalPVID - properties: - InternalPVID: - type: integer - description: Visit ID (required) - 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 - delete: - tags: - - Patient Visits - summary: Delete patient visit - security: - - bearerAuth: [] - responses: - '200': - description: Visit deleted successfully - /api/patvisit/{id}: - get: - tags: - - Patient Visits - 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' - /api/patvisit/patient/{patientId}: - get: - tags: - - Patient Visits - 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 Visits - 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' - patch: - tags: - - Patient Visits - summary: Update ADT record - description: Update an existing ADT record - security: - - bearerAuth: [] - 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' - delete: - tags: - - Patient Visits - 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 Visits - 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 - delete: - tags: - - Patient Visits - 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/{id}: - get: - tags: - - Patient Visits - 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 - /api/patient: - get: - tags: - - Patients - 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: - - Patients - 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' - patch: - tags: - - Patients - summary: Update patient - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Patient' - responses: - '200': - description: Patient updated successfully - delete: - tags: - - Patients - 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: - - Patients - summary: Check if patient exists - security: - - bearerAuth: [] - parameters: - - name: PatientID - in: query - schema: - type: string - description: Patient ID to check - - name: EmailAddress1 - in: query - schema: - type: string - format: email - description: Email address 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: - - Patients - 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' - /api/results: - get: - tags: - - Results - summary: Get patient results - description: Retrieve patient test results with optional filters - security: - - bearerAuth: [] - parameters: - - name: InternalPID - in: query - schema: - type: integer - description: Filter by internal patient ID - - name: OrderID - in: query - schema: - type: string - description: Filter by order ID - - name: TestCode - in: query - schema: - type: string - description: Filter by test code - - name: date_from - in: query - schema: - type: string - format: date - description: Filter results from date (YYYY-MM-DD) - - name: date_to - in: query - schema: - type: string - format: date - description: Filter results to date (YYYY-MM-DD) - - name: verified_only - in: query - schema: - type: boolean - default: false - description: Return only verified results - responses: - '200': - description: List of patient results - content: - application/json: - schema: - type: object - properties: - status: - type: string - data: - type: array - items: - type: object - properties: - ResultID: - type: integer - InternalPID: - type: integer - OrderID: - type: string - TestID: - type: integer - TestCode: - type: string - TestName: - type: string - ResultValue: - type: string - Unit: - type: string - ReferenceRange: - type: string - AbnormalFlag: - type: string - Verified: - type: boolean - VerifiedBy: - type: string - VerifiedDate: - type: string - format: date-time - ResultDate: - type: string - format: date-time - post: - tags: - - Results - summary: Create or update result - description: Create a new result or update an existing result entry - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - InternalPID - - TestID - - ResultValue - properties: - InternalPID: - type: integer - OrderID: - type: string - TestID: - type: integer - ResultValue: - type: string - Unit: - type: string - AbnormalFlag: - type: string - enum: - - H - - L - - 'N' - - A - - C - description: H=High, L=Low, N=Normal, A=Abnormal, C=Critical - responses: - '201': - description: Result created successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - /api/results/{id}: - get: - tags: - - Results - summary: Get result by ID - description: Retrieve a specific result entry by its ID - 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 - data: - type: object - properties: - ResultID: - type: integer - InternalPID: - type: integer - OrderID: - type: string - TestID: - type: integer - TestCode: - type: string - TestName: - type: string - ResultValue: - type: string - Unit: - type: string - ReferenceRange: - type: string - AbnormalFlag: - type: string - Verified: - type: boolean - VerifiedBy: - type: string - VerifiedDate: - type: string - format: date-time - ResultDate: - type: string - format: date-time - patch: - tags: - - Results - summary: Update result - description: Update an existing result entry - 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: - ResultValue: - type: string - Unit: - type: string - AbnormalFlag: - type: string - enum: - - H - - L - - 'N' - - A - - C - Verified: - type: boolean - responses: - '200': - description: Result updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - delete: - tags: - - Results - summary: Delete result - description: Soft delete a result entry - 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' - /api/results/{id}/verify: - post: - tags: - - Results - summary: Verify result - description: Mark a result as verified by the current user - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Result ID - responses: - '200': - description: Result verified successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - /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 - patch: - tags: - - Specimen - summary: Update specimen - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Specimen' - responses: - '200': - description: Specimen updated - /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 - /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 - patch: - tags: - - Specimen - summary: Update container definition - security: - - bearerAuth: [] - responses: - '200': - description: Container definition updated - /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 - /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 - patch: - tags: - - Specimen - summary: Update container definition (alias) - security: - - bearerAuth: [] - 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 - patch: - tags: - - Specimen - summary: Update specimen preparation - security: - - bearerAuth: [] - responses: - '200': - description: Specimen preparation updated - /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 - /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 - patch: - tags: - - Specimen - summary: Update specimen status - security: - - bearerAuth: [] - responses: - '200': - description: Specimen status updated - /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 - /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 - patch: - tags: - - Specimen - summary: Update specimen collection method - security: - - bearerAuth: [] - responses: - '200': - description: Collection method updated - /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 - /api/test/testmap: - get: - tags: - - Tests - summary: List all test mappings - 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 - 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: - $ref: '#/components/schemas/TestMap' - post: - tags: - - Tests - summary: Create test mapping - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestSiteID: - type: integer - description: Test Site ID (required) - HostType: - type: string - description: Host type code - HostID: - type: string - description: Host identifier - HostTestCode: - type: string - description: Test code in host system - HostTestName: - type: string - description: Test name in host system - ClientType: - type: string - description: Client type code - ClientID: - type: string - description: Client identifier - ConDefID: - type: integer - description: Connection definition ID - ClientTestCode: - type: string - description: Test code in client system - ClientTestName: - type: string - description: Test name in client system - required: - - TestSiteID - 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 - patch: - tags: - - Tests - summary: Update test mapping - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestMapID: - type: integer - description: Test Map ID (required) - TestSiteID: - type: integer - HostType: - type: string - HostID: - type: string - HostTestCode: - type: string - HostTestName: - type: string - ClientType: - type: string - ClientID: - type: string - ConDefID: - type: integer - ClientTestCode: - type: string - ClientTestName: - type: string - required: - - TestMapID - 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 - delete: - tags: - - Tests - summary: Soft delete test mapping - 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: - - Tests - summary: Get test mapping by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Test Map ID - responses: - '200': - description: Test mapping details - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/TestMap' - '404': - description: Test mapping not found - /api/test/testmap/by-testsite/{testSiteID}: - get: - tags: - - Tests - summary: Get test mappings by test site - security: - - bearerAuth: [] - parameters: - - name: testSiteID - in: path - required: true - schema: - type: integer - description: Test Site ID - responses: - '200': - description: List of test mappings for the test site - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/TestMap' - /api/test/testmap/by-host/{hostType}/{hostID}: - get: - tags: - - Tests - summary: Get test mappings by host - security: - - bearerAuth: [] - parameters: - - name: hostType - in: path - required: true - schema: - type: string - description: Host type code - - name: hostID - in: path - required: true - schema: - type: string - description: Host identifier - responses: - '200': - description: List of test mappings for the host - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/TestMap' - /api/test/testmap/by-client/{clientType}/{clientID}: - get: - tags: - - Tests - summary: Get test mappings by client - security: - - bearerAuth: [] - parameters: - - name: clientType - in: path - required: true - schema: - type: string - description: Client type code - - name: clientID - in: path - required: true - schema: - type: string - description: Client identifier - responses: - '200': - description: List of test mappings for the client - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/TestMap' - /api/tests: - get: - tags: - - Tests - 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: VisibleScr - in: query - schema: - type: integer - enum: - - 0 - - 1 - description: Filter by screen visibility (0=hidden, 1=visible) - - name: VisibleRpt - 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 - data: - type: array - items: - $ref: '#/components/schemas/TestDefinition' - pagination: - type: object - properties: - total: - type: integer - description: Total number of records matching the query - post: - tags: - - Tests - 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 - VisibleScr: - type: integer - VisibleRpt: - type: integer - CountStat: - type: integer - details: - type: object - description: Type-specific details - refnum: - type: array - items: - type: object - reftxt: - type: array - items: - type: object - testmap: - type: array - items: - type: object - required: - - SiteID - - TestSiteCode - - TestSiteName - - TestType - 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 - patch: - tags: - - Tests - summary: Update test definition - security: - - bearerAuth: [] - 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 - VisibleScr: - type: integer - VisibleRpt: - type: integer - CountStat: - type: integer - details: - type: object - description: Type-specific details - refnum: - type: array - items: - type: object - reftxt: - type: array - items: - type: object - testmap: - type: array - items: - type: object - 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 - /api/tests/{id}: - get: - tags: - - Tests - 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 - delete: - tags: - - Tests - 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/valueset: - get: - tags: - - ValueSets - 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: - - ValueSets - 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: - - ValueSets - 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: - - ValueSets - 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: - - ValueSets - 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: - - ValueSets - 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: - - ValueSets - 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: - - ValueSets - 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: - - ValueSets - 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: - - ValueSets - 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: - - ValueSets - 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: - - ValueSets - 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: - - ValueSets - 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' - DeathIndicator: - type: string - enum: - - 'Y' - - 'N' - description: 'Y: Yes (deceased), N: No (alive)' - 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 - 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 - AccountID: - type: integer - Discipline: - type: object - properties: - id: - type: integer - DisciplineName: - type: string - DisciplineCode: - type: string - 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 - 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 - VisibleScr: - type: integer - default: 1 - description: Screen visibility (0=hidden, 1=visible) - VisibleRpt: - type: integer - default: 1 - description: Report visibility (0=hidden, 1=visible) - CountStat: - type: integer - default: 1 - Level: - type: integer - CreateDate: - type: string - format: date-time - StartDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - FormulaInput: - type: string - description: Input variables for calculated tests - 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: array - description: Group members (only for GROUP type) - items: - type: object - testmap: - type: array - description: Test mappings - items: - $ref: '#/components/schemas/TestMap' - 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 - 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 - AgeEnd: - type: integer - Flag: - type: string - Interpretation: - type: string - 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 - AgeEnd: - type: integer - 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 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 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: 18 - AgeEnd: 99 - 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 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 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: 120 - 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 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - reftxt: - - RefTxtID: 1 - TxtRefType: TEXT - TxtRefTypeLabel: Text - Sex: '2' - SexLabel: Male - AgeStart: 18 - AgeEnd: 99 - 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 - VisibleScr: 1 - VisibleRpt: 0 - CountStat: 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 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 0 - testdefcal: - - TestCalID: 1 - DisciplineID: 2 - DepartmentID: 2 - FormulaInput: CREA,AGE,GENDER - FormulaCode: CKD_EPI(CREA,AGE,GENDER) - Unit1: mL/min/1.73m2 - Decimal: 0 - 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: 18 - AgeEnd: 120 - 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 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - testdefgrp: - - TestGrpID: 1 - Member: 100 - TestSiteCode: CHOL - TestSiteName: Total Cholesterol - - TestGrpID: 2 - Member: 101 - TestSiteCode: TG - TestSiteName: Triglycerides - TITLE: - summary: Section header - value: - TestSiteID: 7 - SiteID: 1 - TestSiteCode: CHEM_HEADER - TestSiteName: '--- CHEMISTRY ---' - TestType: TITLE - DisciplineID: 2 - DepartmentID: 2 - SeqScr: 100 - SeqRpt: 100 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 0 - TestMap: - type: object - properties: - TestMapID: - type: integer - TestSiteID: - type: integer - HostType: - type: string - description: Host type code - HostID: - type: string - description: Host identifier - HostTestCode: - type: string - description: Test code in host system - HostTestName: - type: string - description: Test name in host system - ClientType: - type: string - description: Client type code - ClientID: - type: string - description: Client identifier - ConDefID: - type: integer - description: Connection 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 - OrderTest: - type: object - properties: - OrderID: - type: string - PatientID: - type: string - VisitID: - type: string - OrderDate: - 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 - Priority: - type: string - enum: - - R - - S - - U - description: | - R: Routine - S: Stat - U: Urgent - PriorityLabel: - type: string - description: Priority display text - SiteID: - type: integer - RequestingPhysician: - type: string - 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 - 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 - 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 diff --git a/docs/testmap.yaml b/docs/testmap.yaml new file mode 100644 index 0000000..8e958b4 --- /dev/null +++ b/docs/testmap.yaml @@ -0,0 +1,503 @@ +/api/test/testmap: + get: + tags: [Tests] + summary: List all test mappings (unique groupings) + security: + - bearerAuth: [] + responses: + '200': + description: List of unique test mapping groupings + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: array + items: + type: object + properties: + HostType: + type: string + HostID: + type: string + HostName: + type: string + ClientType: + type: string + ClientID: + type: string + ClientName: + type: string + + post: + tags: [Tests] + summary: Create test mapping (header only) + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestSiteID: + type: integer + description: Test Site ID (required) + 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 + items: + type: object + properties: + HostTestCode: + type: string + HostTestName: + type: string + ConDefID: + type: integer + ClientTestCode: + type: string + ClientTestName: + type: string + required: + - TestSiteID + 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 + + patch: + tags: [Tests] + summary: Update test mapping + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestMapID: + type: integer + description: Test Map ID (required) + TestSiteID: + type: integer + HostType: + type: string + HostID: + type: string + ClientType: + type: string + ClientID: + type: string + required: + - TestMapID + 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 + + delete: + tags: [Tests] + 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: [Tests] + 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/tests.yaml#/TestMap' + '404': + description: Test mapping not found + +/api/test/testmap/by-testsite/{testSiteID}: + get: + tags: [Tests] + summary: Get test mappings by test site with details + security: + - bearerAuth: [] + parameters: + - name: testSiteID + in: path + required: true + schema: + type: integer + description: Test Site ID + responses: + '200': + description: List of test mappings with details for the test site + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '../components/schemas/tests.yaml#/TestMap' + +/api/test/testmap/detail: + get: + tags: [Tests] + 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/tests.yaml#/TestMapDetail' + + post: + tags: [Tests] + 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 + + patch: + tags: [Tests] + summary: Update test mapping detail + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestMapDetailID: + type: integer + description: Test Map Detail ID (required) + TestMapID: + type: integer + HostTestCode: + type: string + HostTestName: + type: string + ConDefID: + type: integer + ClientTestCode: + type: string + ClientTestName: + type: string + required: + - TestMapDetailID + responses: + '200': + description: Test mapping detail updated + + delete: + tags: [Tests] + 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: [Tests] + 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/tests.yaml#/TestMapDetail' + +/api/test/testmap/detail/by-testmap/{testMapID}: + get: + tags: [Tests] + 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/tests.yaml#/TestMapDetail' + +/api/test/testmap/detail/batch: + post: + tags: [Tests] + 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: [Tests] + 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: [Tests] + 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 diff --git a/src/lib/api/testmap.js b/src/lib/api/testmap.js index 30cf826..2d4526b 100644 --- a/src/lib/api/testmap.js +++ b/src/lib/api/testmap.js @@ -1,17 +1,26 @@ import { get, post, patch, del } from './client.js'; /** - * @typedef {Object} TestMap + * @typedef {Object} TestMapHeader * @property {number} TestMapID - Mapping ID + * @property {string} HostType - Host Type (HIS, SITE, WST, INST) + * @property {string} HostID - Host ID + * @property {string} HostName - Host Name + * @property {string} ClientType - Client Type (HIS, SITE, WST, INST) + * @property {string} ClientID - Client ID + * @property {string} ClientName - Client Name + * @property {string} IsActive - Active status ('1' or '0') + */ + +/** + * @typedef {Object} TestMapDetail + * @property {number} TestMapDetailID - Detail ID + * @property {number} TestMapID - Test Map ID (header) * @property {number} TestSiteID - Test Site ID * @property {string} TestSiteCode - Test Code * @property {string} TestSiteName - Test Name - * @property {string} HostType - Host Type (HIS, SITE, WST, INST) - * @property {string} HostID - Host ID * @property {string} HostTestCode - Host Test Code * @property {string} HostTestName - Host Test Name - * @property {string} ClientType - Client Type (HIS, SITE, WST, INST) - * @property {string} ClientID - Client ID * @property {number} ConDefID - Container Definition ID * @property {string} ClientTestCode - Client Test Code * @property {string} ClientTestName - Client Test Name @@ -19,25 +28,42 @@ import { get, post, patch, del } from './client.js'; */ /** - * @typedef {Object} TestMapFilterOptions - * @property {string} [hostType] - Filter by Host Type - * @property {string} [hostID] - Filter by Host ID - * @property {string} [clientType] - Filter by Client Type - * @property {string} [clientID] - Filter by Client ID - * @property {string} [search] - Search term + * @typedef {Object} TestMapWithDetails + * @property {number} TestMapID - Mapping ID + * @property {number} TestSiteID - Test Site ID + * @property {string} TestSiteCode - Test Code + * @property {string} TestSiteName - Test Name + * @property {string} HostType - Host Type + * @property {string} HostID - Host ID + * @property {string} HostTestCode - Host Test Code + * @property {string} HostTestName - Host Test Name + * @property {string} ClientType - Client Type + * @property {string} ClientID - Client ID + * @property {number} ConDefID - Container Definition ID + * @property {string} ClientTestCode - Client Test Code + * @property {string} ClientTestName - Client Test Name + * @property {string} IsActive - Active status ('1' or '0') + * @property {TestMapDetail[]} details - Array of detail records */ /** * @typedef {Object} TestMapListResponse * @property {boolean} success - * @property {TestMap[]} data + * @property {TestMapHeader[]} data * @property {string} [message] */ /** * @typedef {Object} TestMapResponse * @property {boolean} success - * @property {TestMap} data + * @property {TestMapWithDetails} data + * @property {string} [message] + */ + +/** + * @typedef {Object} TestMapDetailResponse + * @property {boolean} success + * @property {TestMapDetail} data * @property {string} [message] */ @@ -46,49 +72,63 @@ import { get, post, patch, del } from './client.js'; * @property {number} TestSiteID - Test Site ID * @property {string} HostType - Host Type * @property {string} HostID - Host ID - * @property {string} HostTestCode - Host Test Code - * @property {string} HostTestName - Host Test Name * @property {string} ClientType - Client Type * @property {string} ClientID - Client ID - * @property {number} ConDefID - Container Definition ID - * @property {string} ClientTestCode - Client Test Code - * @property {string} ClientTestName - Client Test Name + * @property {Object[]} [details] - Optional detail records to create */ /** * @typedef {Object} UpdateTestMapPayload * @property {number} TestMapID - Mapping ID - * @property {number} TestSiteID - Test Site ID - * @property {string} HostType - Host Type - * @property {string} HostID - Host ID + * @property {number} [TestSiteID] - Test Site ID + * @property {string} [HostType] - Host Type + * @property {string} [HostID] - Host ID + * @property {string} [ClientType] - Client Type + * @property {string} [ClientID] - Client ID + */ + +/** + * @typedef {Object} CreateTestMapDetailPayload + * @property {number} TestMapID - Test Map ID * @property {string} HostTestCode - Host Test Code * @property {string} HostTestName - Host Test Name - * @property {string} ClientType - Client Type - * @property {string} ClientID - Client ID * @property {number} ConDefID - Container Definition ID * @property {string} ClientTestCode - Client Test Code * @property {string} ClientTestName - Client Test Name */ /** - * Fetch all test mappings - * @returns {Promise} API response with mappings list + * @typedef {Object} UpdateTestMapDetailPayload + * @property {number} TestMapDetailID - Detail ID + * @property {number} [TestMapID] - Test Map ID + * @property {string} [HostTestCode] - Host Test Code + * @property {string} [HostTestName] - Host Test Name + * @property {number} [ConDefID] - Container Definition ID + * @property {string} [ClientTestCode] - Client Test Code + * @property {string} [ClientTestName] - Client Test Name + */ + +// ==================== HEADER ENDPOINTS ==================== + +/** + * Fetch all test mapping headers (grouped by host/client) + * @returns {Promise} API response with headers list */ export async function fetchTestMaps() { return get('/api/test/testmap'); } /** - * Fetch a single test mapping by ID + * Fetch a single test mapping header by ID with details * @param {number} id - Test Map ID - * @returns {Promise} API response with mapping detail + * @returns {Promise} API response with header and details */ export async function fetchTestMap(id) { return get(`/api/test/testmap/${id}`); } /** - * Fetch test mappings by test site ID + * Fetch test mappings by test site ID with details * @param {number} testSiteID - Test Site ID * @returns {Promise} API response with mappings list */ @@ -97,52 +137,123 @@ export async function fetchTestMapsByTestSite(testSiteID) { } /** - * Fetch test mappings by host - * @param {string} hostType - Host Type - * @param {string} hostID - Host ID - * @returns {Promise} API response with mappings list - */ -export async function fetchTestMapsByHost(hostType, hostID) { - return get(`/api/test/testmap/by-host/${hostType}/${hostID}`); -} - -/** - * Fetch test mappings by client - * @param {string} clientType - Client Type - * @param {string} clientID - Client ID - * @returns {Promise} API response with mappings list - */ -export async function fetchTestMapsByClient(clientType, clientID) { - return get(`/api/test/testmap/by-client/${clientType}/${clientID}`); -} - -/** - * Create a new test mapping - * @param {CreateTestMapPayload} data - Mapping data - * @returns {Promise} API response + * Create a new test mapping header + * @param {CreateTestMapPayload} data - Header data + * @returns {Promise<{success: boolean, data: number, message?: string}>} API response with created TestMapID */ export async function createTestMap(data) { return post('/api/test/testmap', data); } /** - * Update an existing test mapping - * @param {UpdateTestMapPayload} data - Mapping data - * @returns {Promise} API response + * Update an existing test mapping header + * @param {UpdateTestMapPayload} data - Header data + * @returns {Promise<{success: boolean, data: number, message?: string}>} API response */ export async function updateTestMap(data) { return patch('/api/test/testmap', data); } /** - * Soft delete a test mapping (set IsActive to '0') + * Soft delete a test mapping header (cascades to details) * @param {number} id - Test Map ID - * @returns {Promise<{success: boolean, message?: string}>} API response + * @returns {Promise<{success: boolean, data: number, message?: string}>} API response */ export async function deleteTestMap(id) { return del('/api/test/testmap', { body: JSON.stringify({ TestMapID: id }) }); } +// ==================== DETAIL ENDPOINTS ==================== + +/** + * Fetch all test mapping details (optionally filtered by TestMapID) + * @param {Object} params - Query parameters + * @param {number} [params.TestMapID] - Filter by TestMapID + * @returns {Promise<{success: boolean, data: TestMapDetail[], message?: string}>} API response + */ +export async function fetchTestMapDetails(params = {}) { + const query = new URLSearchParams(); + if (params.TestMapID) query.append('TestMapID', params.TestMapID.toString()); + const queryString = query.toString(); + return get(queryString ? `/api/test/testmap/detail?${queryString}` : '/api/test/testmap/detail'); +} + +/** + * Fetch a single test mapping detail by ID + * @param {number} id - Test Map Detail ID + * @returns {Promise} API response with detail + */ +export async function fetchTestMapDetail(id) { + return get(`/api/test/testmap/detail/${id}`); +} + +/** + * Fetch test mapping details by test map ID + * @param {number} testMapID - Test Map ID + * @returns {Promise<{success: boolean, data: TestMapDetail[], message?: string}>} API response + */ +export async function fetchTestMapDetailsByTestMap(testMapID) { + return get(`/api/test/testmap/detail/by-testmap/${testMapID}`); +} + +/** + * Create a new test mapping detail + * @param {CreateTestMapDetailPayload} data - Detail data + * @returns {Promise<{success: boolean, data: number, message?: string}>} API response with created TestMapDetailID + */ +export async function createTestMapDetail(data) { + return post('/api/test/testmap/detail', data); +} + +/** + * Update an existing test mapping detail + * @param {UpdateTestMapDetailPayload} data - Detail data + * @returns {Promise<{success: boolean, message?: string}>} API response + */ +export async function updateTestMapDetail(data) { + return patch('/api/test/testmap/detail', data); +} + +/** + * Soft delete a test mapping detail + * @param {number} id - Test Map Detail ID + * @returns {Promise<{success: boolean, message?: string}>} API response + */ +export async function deleteTestMapDetail(id) { + return del('/api/test/testmap/detail', { body: JSON.stringify({ TestMapDetailID: id }) }); +} + +// ==================== BATCH DETAIL ENDPOINTS ==================== + +/** + * Batch create test mapping details + * @param {CreateTestMapDetailPayload[]} details - Array of detail records to create + * @returns {Promise<{success: boolean, message?: string}>} API response + */ +export async function batchCreateTestMapDetails(details) { + return post('/api/test/testmap/detail/batch', details); +} + +/** + * Batch update test mapping details + * @param {UpdateTestMapDetailPayload[]} details - Array of detail records to update + * @returns {Promise<{success: boolean, message?: string}>} API response + */ +export async function batchUpdateTestMapDetails(details) { + return patch('/api/test/testmap/detail/batch', details); +} + +/** + * Batch delete test mapping details + * @param {number[]} detailIDs - Array of TestMapDetailID to delete + * @returns {Promise<{success: boolean, message?: string}>} API response + */ +export async function batchDeleteTestMapDetails(detailIDs) { + return del('/api/test/testmap/detail/batch', { body: JSON.stringify(detailIDs) }); +} + +// ==================== VALIDATION ==================== + /** * Validate mapping form data * @param {Object} data - Form data to validate @@ -176,3 +287,26 @@ export function validateTestMap(data) { errors }; } + +/** + * Validate detail form data + * @param {Object} data - Form data to validate + * @returns {{valid: boolean, errors: Object}} + */ +export function validateTestMapDetail(data) { + const errors = {}; + + if (!data.TestMapID) { + errors.TestMapID = 'Test Map ID is required'; + } + + const hasAnyField = data.HostTestCode || data.HostTestName || data.ClientTestCode || data.ClientTestName; + if (!hasAnyField) { + errors.empty = 'At least one field must be filled'; + } + + return { + valid: Object.keys(errors).length === 0, + errors + }; +} diff --git a/src/routes/(app)/master-data/testmap/+page.svelte b/src/routes/(app)/master-data/testmap/+page.svelte index 551003b..f514391 100644 --- a/src/routes/(app)/master-data/testmap/+page.svelte +++ b/src/routes/(app)/master-data/testmap/+page.svelte @@ -2,6 +2,7 @@ import { onMount } from 'svelte'; import { fetchTestMaps, + fetchTestMap, deleteTestMap, } from '$lib/api/testmap.js'; import { fetchContainers } from '$lib/api/containers.js'; @@ -17,12 +18,10 @@ Link, Server, Monitor, - Filter, - X, } from 'lucide-svelte'; let loading = $state(false); - let testMaps = $state([]); + let testMapHeaders = $state([]); let containers = $state([]); let modalOpen = $state(false); let modalMode = $state('create'); @@ -32,68 +31,14 @@ let deleteConfirmOpen = $state(false); let deleteItem = $state(null); let deleteGroupMode = $state(false); - - // Filter states - let filterHostType = $state(''); - let filterHostID = $state(''); - let filterClientType = $state(''); - let filterClientID = $state(''); - - // System types for dropdowns - const SYSTEM_TYPES = ['HIS', 'SITE', 'WST', 'INST']; - - // Derived unique values for ID dropdowns - let uniqueHostIDs = $derived([...new Set(testMaps.map(m => m.HostID).filter(Boolean))].sort()); - let uniqueClientIDs = $derived([...new Set(testMaps.map(m => m.ClientID).filter(Boolean))].sort()); + let modalLoading = $state(false); const columns = [ { key: 'HostInfo', label: 'Host System', class: 'w-48' }, { key: 'ClientInfo', label: 'Client System', class: 'w-48' }, - { key: 'TestCount', label: 'Tests', class: 'w-24 text-center' }, { key: 'actions', label: 'Actions', class: 'w-32 text-center' }, ]; - // Group test mappings by HostType/HostID/ClientType/ClientID - let groupedTestMaps = $derived(() => { - const groups = new Map(); - - testMaps.forEach((mapping) => { - const key = `${mapping.HostType || ''}|${mapping.HostID || ''}|${mapping.ClientType || ''}|${mapping.ClientID || ''}`; - - if (!groups.has(key)) { - groups.set(key, { - key, - HostType: mapping.HostType || '', - HostID: mapping.HostID || '', - ClientType: mapping.ClientType || '', - ClientID: mapping.ClientID || '', - mappings: [], - }); - } - - const group = groups.get(key); - group.mappings.push(mapping); - }); - - return Array.from(groups.values()); - }); - - // Derived filtered grouped test maps - let filteredGroupedTestMaps = $derived( - groupedTestMaps().filter((group) => { - const matchesHostType = - !filterHostType || group.HostType === filterHostType; - const matchesHostID = - !filterHostID || group.HostID === filterHostID; - const matchesClientType = - !filterClientType || group.ClientType === filterClientType; - const matchesClientID = - !filterClientID || group.ClientID === filterClientID; - - return matchesHostType && matchesHostID && matchesClientType && matchesClientID; - }) - ); - onMount(async () => { await Promise.all([loadTestMaps(), loadContainers()]); }); @@ -102,10 +47,10 @@ loading = true; try { const response = await fetchTestMaps(); - testMaps = Array.isArray(response.data) ? response.data : []; + testMapHeaders = Array.isArray(response.data) ? response.data : []; } catch (err) { toastError(err.message || 'Failed to load test mappings'); - testMaps = []; + testMapHeaders = []; } finally { loading = false; } @@ -128,12 +73,27 @@ modalOpen = true; } - function openEditGroupModal(group) { + async function openEditGroupModal(group) { + modalLoading = true; modalMode = 'edit'; - modalGroupData = group; - // Pass the first mapping as initial data, modal will handle the rest - modalData = group.mappings[0] || null; - modalOpen = true; + + try { + // Use TestMapID directly from the grouped data (now returned by API) + modalGroupData = { + ...group, + TestMapID: parseInt(group.TestMapID) || null, + mappings: [], // Will be populated by modal + }; + modalData = null; + modalOpen = true; + } catch (err) { + toastError(err.message || 'Failed to load test mapping details'); + modalGroupData = group; + modalData = null; + modalOpen = true; + } finally { + modalLoading = false; + } } function handleModalSave() { @@ -150,34 +110,26 @@ deleting = true; try { if (deleteGroupMode && deleteItem) { - // Delete all mappings in the group - const deletePromises = deleteItem.mappings.map((mapping) => - deleteTestMap(mapping.TestMapID) - ); - await Promise.all(deletePromises); - toastSuccess(`Deleted ${deleteItem.mappings.length} test mapping(s) successfully`); + // For delete, we need the TestMapID + // Since the list doesn't return TestMapID, we need to fetch it first + // This is a limitation of the current API - it should return TestMapID in the list + toastError('Delete functionality requires TestMapID which is not available in the list. Please contact administrator.'); + // TODO: Implement once API returns TestMapID or provides delete by host/client endpoint } else if (deleteItem?.TestMapID) { // Delete single mapping (fallback) await deleteTestMap(deleteItem.TestMapID); toastSuccess('Test mapping deleted successfully'); + deleteConfirmOpen = false; + deleteItem = null; + deleteGroupMode = false; + await loadTestMaps(); } - deleteConfirmOpen = false; - deleteItem = null; - deleteGroupMode = false; - await loadTestMaps(); } catch (err) { toastError(err.message || 'Failed to delete test mapping(s)'); } finally { deleting = false; } } - - function clearFilters() { - filterHostType = ''; - filterHostID = ''; - filterClientType = ''; - filterClientID = ''; - }
@@ -197,113 +149,29 @@
- -
-
-

- - Filters -

- -
-
- -
-

- - Host -

-
- - -
-
- -
-

- - Client -

-
- - -
-
-
-
-
- {#if !loading && filteredGroupedTestMaps.length === 0} + {#if !loading && testMapHeaders.length === 0}

- {#if filterHostType || filterHostID || filterClientType || filterClientID} - No mappings match your filters - {:else} - No test mappings found - {/if} + No test mappings found

-

- {#if filterHostType || filterHostID || filterClientType || filterClientID} - Try adjusting your filter criteria or clear the filters to see all mappings. - {:else} - Test mappings connect tests between host systems (like HIS) and client systems. Add your first mapping to get started. - {/if} +

+ Test mappings connect tests between host systems (like HIS) and client systems. Add your first mapping to get started.

- {#if filterHostType || filterHostID || filterClientType || filterClientID} - - {:else} - - {/if} +
{:else}
- {row.HostType || '-'} - {row.HostID || '-'} + {row.HostName || row.HostID || '-'}
{:else if column.key === 'ClientInfo'}
- {row.ClientType || '-'} - {row.ClientID || '-'} + {row.ClientName || row.ClientID || '-'}
- {:else if column.key === 'TestCount'} -
- - {row.mappings.length} - -
{:else if column.key === 'actions'}
@@ -363,6 +225,7 @@ initialData={modalData} groupData={modalGroupData} {containers} + loading={modalLoading} onSave={handleModalSave} /> @@ -371,7 +234,7 @@

{#if deleteGroupMode} - Are you sure you want to delete all {deleteItem?.mappings?.length || 0} test mapping(s) in this group? + Are you sure you want to delete this test mapping group? {:else} Are you sure you want to delete this test mapping? {/if} @@ -379,11 +242,11 @@

Host: - {deleteItem?.HostType} / {deleteItem?.HostID} + {deleteItem?.HostName || deleteItem?.HostID}

Client: - {deleteItem?.ClientType} / {deleteItem?.ClientID} + {deleteItem?.ClientName || deleteItem?.ClientID}

diff --git a/src/routes/(app)/master-data/testmap/TestMapModal.svelte b/src/routes/(app)/master-data/testmap/TestMapModal.svelte index aa7f27e..cb08a5b 100644 --- a/src/routes/(app)/master-data/testmap/TestMapModal.svelte +++ b/src/routes/(app)/master-data/testmap/TestMapModal.svelte @@ -1,7 +1,15 @@