diff --git a/.cocoindex_code/cocoindex.db/mdb/data.mdb b/.cocoindex_code/cocoindex.db/mdb/data.mdb deleted file mode 100644 index f0a50dd..0000000 Binary files a/.cocoindex_code/cocoindex.db/mdb/data.mdb and /dev/null differ diff --git a/.cocoindex_code/cocoindex.db/mdb/lock.mdb b/.cocoindex_code/cocoindex.db/mdb/lock.mdb deleted file mode 100644 index 904f87c..0000000 Binary files a/.cocoindex_code/cocoindex.db/mdb/lock.mdb and /dev/null differ diff --git a/.cocoindex_code/settings.yml b/.cocoindex_code/settings.yml deleted file mode 100644 index c910c16..0000000 --- a/.cocoindex_code/settings.yml +++ /dev/null @@ -1,41 +0,0 @@ -exclude_patterns: -- '**/.*' -- '**/__pycache__' -- '**/node_modules' -- '**/target' -- '**/build/assets' -- '**/dist' -- '**/vendor/*.*/*' -- '**/vendor/*' -- '**/.cocoindex_code' -include_patterns: -- '**/*.py' -- '**/*.pyi' -- '**/*.js' -- '**/*.jsx' -- '**/*.ts' -- '**/*.tsx' -- '**/*.mjs' -- '**/*.cjs' -- '**/*.rs' -- '**/*.go' -- '**/*.java' -- '**/*.c' -- '**/*.h' -- '**/*.cpp' -- '**/*.hpp' -- '**/*.cc' -- '**/*.cxx' -- '**/*.hxx' -- '**/*.hh' -- '**/*.cs' -- '**/*.sql' -- '**/*.sh' -- '**/*.bash' -- '**/*.zsh' -- '**/*.md' -- '**/*.mdx' -- '**/*.txt' -- '**/*.rst' -- '**/*.php' -- '**/*.lua' diff --git a/.cocoindex_code/target_sqlite.db b/.cocoindex_code/target_sqlite.db deleted file mode 100644 index 36614e4..0000000 Binary files a/.cocoindex_code/target_sqlite.db and /dev/null differ diff --git a/docs/api-docs.bundled.yaml b/docs/api-docs.bundled.yaml deleted file mode 100644 index 3ce3e13..0000000 --- a/docs/api-docs.bundled.yaml +++ /dev/null @@ -1,8137 +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: Patient - description: Patient registration and management - - name: Patient Visit - description: Patient visit/encounter management - - name: Organization - description: Organization structure (accounts, sites, disciplines, departments, workstations) - - name: Location - description: Location management (rooms, wards, buildings) - - name: Equipment - description: Laboratory equipment and instrument management - - name: Specimen - description: Specimen and container management - - name: Test - description: Test definitions and test catalog - - name: Rule - description: Rule engine - rules can be linked to multiple tests via testrule mapping table - - name: Calculation - description: Lightweight calculator endpoint for retrieving computed values by code or name - - name: Order - description: Laboratory order management - - name: Result - description: Patient results reporting with auto-validation - - name: Report - description: Lab report generation (HTML view) - - name: Edge API - description: Instrument integration endpoints - - name: Contact - description: Contact management (doctors, practitioners, etc.) - - name: ValueSet - description: Value set definitions and items - - name: User - description: User management and administration - - name: Demo - description: Demo/test endpoints (no authentication) -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/calc/testcode/{codeOrName}: - post: - tags: - - Calculation - summary: Evaluate a configured calculation by test code or name and return the raw result map. - security: [] - parameters: - - name: codeOrName - in: path - required: true - schema: - type: string - description: TestSiteCode or TestSiteName of the calculated test (case-insensitive). - requestBody: - required: true - content: - application/json: - schema: - type: object - description: Key-value pairs where keys match member tests used in the formula. - additionalProperties: - type: number - example: - TBIL: 5 - DBIL: 3 - responses: - '200': - description: Returns a single key/value pair with the canonical TestSiteCode or an empty object when the calculation is incomplete or missing. - content: - application/json: - schema: - type: object - examples: - success: - value: - IBIL: 2 - incomplete: - value: {} - /api/calc/testsite/{testSiteID}: - post: - tags: - - Calculation - summary: Evaluate a calculation defined for a test site and return a structured result. - security: [] - parameters: - - name: testSiteID - in: path - required: true - schema: - type: integer - description: Identifier for the test site whose definition should be evaluated. - requestBody: - required: true - content: - application/json: - schema: - type: object - description: Variable assignments required by the test site formula. - additionalProperties: - type: number - example: - result: 85 - gender: female - age: 30 - responses: - '200': - description: Returns the calculated result, testSiteID, formula code, and echoed variables. - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - data: - type: object - properties: - result: - type: number - testSiteID: - type: integer - formula: - type: string - variables: - type: object - additionalProperties: - type: number - examples: - success: - value: - status: success - data: - result: 92.4 - testSiteID: 123 - formula: '{result} * {factor} + {age}' - variables: - result: 85 - gender: female - age: 30 - '404': - description: No calculation defined for the requested test site. - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: failed - message: - type: string - example: No calculation defined for this test site - /api/contact: - get: - tags: - - Contact - summary: List contacts - security: - - bearerAuth: [] - parameters: - - name: ContactName - in: query - schema: - type: string - description: Filter by contact name (searches in NameFirst and NameLast) - - name: Specialty - in: query - schema: - type: string - description: Filter by medical specialty code - responses: - '200': - description: List of contacts - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/Contact' - post: - tags: - - Contact - summary: Create new contact - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - NameFirst - properties: - NameFirst: - type: string - description: First name - NameLast: - type: string - description: Last name - Title: - type: string - description: Title (e.g., Dr, Mr, Mrs) - Initial: - type: string - description: Middle initial - Birthdate: - type: string - format: date-time - description: Date of birth - EmailAddress1: - type: string - format: email - description: Primary email address - EmailAddress2: - type: string - format: email - description: Secondary email address - Phone: - type: string - description: Primary phone number - MobilePhone1: - type: string - description: Primary mobile number - MobilePhone2: - type: string - description: Secondary mobile number - Specialty: - type: string - description: Medical specialty code - SubSpecialty: - type: string - description: Sub-specialty code - responses: - '201': - description: Contact created successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - '422': - description: Validation error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - delete: - tags: - - Contact - summary: Delete contact - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - ContactID - properties: - ContactID: - type: integer - description: Contact ID to delete - responses: - '200': - description: Contact deleted successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - /api/contact/{id}: - get: - tags: - - Contact - summary: Get contact by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Contact ID - responses: - '200': - description: Contact details - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/Contact' - patch: - tags: - - Contact - summary: Update contact - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Contact ID to update - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - NameFirst - properties: - NameFirst: - type: string - description: First name - NameLast: - type: string - description: Last name - Title: - type: string - description: Title (e.g., Dr, Mr, Mrs) - Initial: - type: string - description: Middle initial - Birthdate: - type: string - format: date-time - description: Date of birth - EmailAddress1: - type: string - format: email - description: Primary email address - EmailAddress2: - type: string - format: email - description: Secondary email address - Phone: - type: string - description: Primary phone number - MobilePhone1: - type: string - description: Primary mobile number - MobilePhone2: - type: string - description: Secondary mobile number - Specialty: - type: string - description: Medical specialty code - SubSpecialty: - type: string - description: Sub-specialty code - responses: - '201': - description: Contact updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - '422': - description: Validation error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /api/demo/hello: - get: - tags: - - Demo - summary: Hello world endpoint - description: Simple test endpoint that returns a greeting message - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: Hello, World! - /api/demo/ping: - get: - tags: - - Demo - summary: Ping endpoint - description: Health check endpoint to verify API is running - responses: - '200': - description: API is running - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: pong - timestamp: - type: string - format: date-time - /api/edge/result: - post: - tags: - - Edge API - summary: Receive results from instrument (tiny-edge) - description: | - Receives instrument results and stores them in the edgeres table for processing. - This endpoint is typically called by the tiny-edge middleware connected to laboratory analyzers. - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/EdgeResultRequest' - responses: - '201': - description: Result received and queued - content: - application/json: - schema: - $ref: '#/components/schemas/EdgeResultResponse' - '400': - description: Invalid JSON payload - /api/edge/order: - get: - tags: - - Edge API - summary: Fetch pending orders for instruments - description: Returns orders that need to be sent to laboratory instruments for testing - parameters: - - name: instrument_id - in: query - schema: - type: string - description: Filter by instrument - - name: status - in: query - schema: - type: string - enum: - - pending - - acknowledged - description: Filter by status - responses: - '200': - description: List of orders - content: - application/json: - schema: - type: object - properties: - status: - type: string - data: - type: array - items: - $ref: '#/components/schemas/EdgeOrder' - /api/edge/order/{orderId}/ack: - post: - tags: - - Edge API - summary: Acknowledge order delivery - description: Mark order as acknowledged by the instrument - parameters: - - name: orderId - in: path - required: true - schema: - type: integer - description: Edge order ID - responses: - '200': - description: Order acknowledged - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - /api/edge/status: - post: - tags: - - Edge API - summary: Log instrument status update - description: Receive status updates from laboratory instruments - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - instrument_id - - status - properties: - instrument_id: - type: string - status: - type: string - enum: - - online - - offline - - error - - maintenance - message: - type: string - timestamp: - type: string - format: date-time - responses: - '200': - description: Status logged - /api/equipmentlist: - get: - tags: - - Equipment - summary: List equipment - description: Get list of equipment with optional filters - security: - - bearerAuth: [] - parameters: - - name: IEID - in: query - schema: - type: string - description: Filter by IEID - - name: InstrumentName - in: query - schema: - type: string - description: Filter by instrument name - - name: DepartmentID - in: query - schema: - type: integer - description: Filter by department ID - - name: WorkstationID - in: query - schema: - type: integer - description: Filter by workstation ID - - name: Enable - in: query - schema: - type: integer - enum: - - 0 - - 1 - description: Filter by enable status - responses: - '200': - description: List of equipment - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/EquipmentList' - post: - tags: - - Equipment - summary: Create equipment - description: Create a new equipment entry - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - IEID - - DepartmentID - - Enable - - EquipmentRole - properties: - IEID: - type: string - maxLength: 50 - DepartmentID: - type: integer - InstrumentID: - type: string - maxLength: 150 - InstrumentName: - type: string - maxLength: 150 - WorkstationID: - type: integer - Enable: - type: integer - enum: - - 0 - - 1 - EquipmentRole: - type: string - maxLength: 1 - responses: - '201': - description: Equipment created - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: integer - delete: - tags: - - Equipment - summary: Delete equipment - description: Soft delete an equipment entry - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - EID - properties: - EID: - type: integer - responses: - '200': - description: Equipment deleted - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - /api/equipmentlist/{id}: - get: - tags: - - Equipment - summary: Get equipment by ID - description: Get a single equipment entry by its EID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Equipment ID - responses: - '200': - description: Equipment details - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/EquipmentList' - patch: - tags: - - Equipment - summary: Update equipment - description: Update an existing equipment entry - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Equipment ID - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - IEID: - type: string - maxLength: 50 - DepartmentID: - type: integer - InstrumentID: - type: string - maxLength: 150 - InstrumentName: - type: string - maxLength: 150 - WorkstationID: - type: integer - Enable: - type: integer - enum: - - 0 - - 1 - EquipmentRole: - type: string - maxLength: 1 - responses: - '200': - description: Equipment updated - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: integer - /api/location: - get: - tags: - - Location - summary: List locations - security: - - bearerAuth: [] - parameters: - - name: LocCode - in: query - schema: - type: string - description: Filter by location code - - name: LocName - in: query - schema: - type: string - description: Filter by location name (searches in LocFull) - responses: - '200': - description: List of locations - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/Location' - post: - tags: - - Location - summary: Create location - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - LocCode - - LocFull - properties: - SiteID: - type: integer - description: Reference to site - LocCode: - type: string - maxLength: 6 - description: Location code (short identifier) - Parent: - type: integer - nullable: true - description: Parent location ID for hierarchical locations - LocFull: - type: string - maxLength: 255 - description: Full location name - Description: - type: string - maxLength: 255 - description: Location description - LocType: - type: string - description: Location type code (e.g., ROOM, WARD, BUILDING) - responses: - '201': - description: Location created successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - '422': - description: Validation error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - delete: - tags: - - Location - summary: Delete location - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - LocationID - properties: - LocationID: - type: integer - description: Location ID to delete - responses: - '200': - description: Location deleted successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - /api/location/{id}: - get: - tags: - - Location - summary: Get location by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Location ID - responses: - '200': - description: Location details - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/Location' - patch: - tags: - - Location - summary: Update location - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Location ID to update - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - SiteID: - type: integer - description: Reference to site - LocCode: - type: string - maxLength: 6 - description: Location code (short identifier) - Parent: - type: integer - nullable: true - description: Parent location ID for hierarchical locations - LocFull: - type: string - maxLength: 255 - description: Full location name - Description: - type: string - maxLength: 255 - description: Location description - LocType: - type: string - description: Location type code (e.g., ROOM, WARD, BUILDING) - responses: - '201': - description: Location updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - '422': - description: Validation error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /api/ordertest: - get: - tags: - - Order - summary: List orders - security: - - bearerAuth: [] - parameters: - - name: page - in: query - schema: - type: integer - - name: perPage - in: query - schema: - type: integer - - name: InternalPID - in: query - schema: - type: integer - description: Filter by internal patient ID - - name: OrderStatus - in: query - schema: - type: string - enum: - - ORD - - SCH - - ANA - - VER - - REV - - REP - description: | - ORD: Ordered - SCH: Scheduled - ANA: Analysis - VER: Verified - REV: Reviewed - REP: Reported - responses: - '200': - description: List of orders - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/OrderTestList' - post: - tags: - - Order - summary: Create order with specimens and tests - description: Creates an order with associated specimens and patres records. Tests are grouped by container type to minimize specimen creation. - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - InternalPID - - Tests - properties: - OrderID: - type: string - description: Optional custom order ID (auto-generated if not provided) - InternalPID: - type: integer - description: Patient internal ID - PatVisitID: - type: integer - description: Visit ID - SiteID: - type: integer - default: 1 - PlacerID: - type: string - Priority: - type: string - enum: - - R - - S - - U - default: R - description: | - R: Routine - S: Stat - U: Urgent - ReqApp: - type: string - description: Requesting application - Comment: - type: string - Tests: - type: array - items: - type: object - required: - - TestSiteID - properties: - TestSiteID: - type: integer - description: Test definition site ID - TestID: - type: integer - description: Alias for TestSiteID - responses: - '201': - description: Order created successfully with specimens and tests - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - $ref: '#/components/schemas/OrderTest' - '400': - description: Validation error - '500': - description: Server error - delete: - tags: - - Order - summary: Delete order - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - OrderID - properties: - OrderID: - type: string - responses: - '200': - description: Order deleted - /api/ordertest/status: - post: - tags: - - Order - summary: Update order status - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - OrderID - - OrderStatus - properties: - OrderID: - type: string - OrderStatus: - type: string - enum: - - ORD - - SCH - - ANA - - VER - - REV - - REP - description: | - ORD: Ordered - SCH: Scheduled - ANA: Analysis - VER: Verified - REV: Reviewed - REP: Reported - responses: - '200': - description: Order status updated - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/OrderTest' - /api/ordertest/{id}: - get: - tags: - - Order - summary: Get order by ID - description: Returns order details with associated specimens and tests - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - description: Order ID (e.g., 0025030300001) - responses: - '200': - description: Order details with specimens and tests - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/OrderTest' - patch: - tags: - - Order - summary: Update order - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - description: Order ID - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - Priority: - type: string - enum: - - R - - S - - U - OrderStatus: - type: string - enum: - - ORD - - SCH - - ANA - - VER - - REV - - REP - OrderingProvider: - type: string - DepartmentID: - type: integer - WorkstationID: - type: integer - responses: - '200': - description: Order updated - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/OrderTest' - /api/organization/account/{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 - delete: - tags: - - Organization - summary: Delete site - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - responses: - '200': - description: Site deleted - /api/organization/site/{id}: - get: - tags: - - Organization - summary: Get site by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Site details - patch: - tags: - - Organization - summary: Update site - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - SiteName: - type: string - SiteCode: - type: string - AccountID: - type: integer - responses: - '200': - description: Site updated - /api/organization/discipline: - get: - tags: - - Organization - summary: List disciplines - security: - - bearerAuth: [] - responses: - '200': - description: List of disciplines - post: - tags: - - Organization - summary: Create discipline - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Discipline' - responses: - '201': - description: Discipline created - delete: - tags: - - Organization - summary: Delete discipline - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - responses: - '200': - description: Discipline deleted - /api/organization/discipline/{id}: - get: - tags: - - Organization - summary: Get discipline by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Discipline details - patch: - tags: - - Organization - summary: Update discipline - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - DisciplineName: - type: string - DisciplineCode: - type: string - SeqScr: - type: integer - description: Display order on screen - SeqRpt: - type: integer - description: Display order in reports - responses: - '200': - description: Discipline updated - /api/organization/department: - get: - tags: - - Organization - summary: List departments - security: - - bearerAuth: [] - responses: - '200': - description: List of departments - post: - tags: - - Organization - summary: Create department - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Department' - responses: - '201': - description: Department created - delete: - tags: - - Organization - summary: Delete department - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - responses: - '200': - description: Department deleted - /api/organization/department/{id}: - get: - tags: - - Organization - summary: Get department by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Department details - patch: - tags: - - Organization - summary: Update department - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - DeptName: - type: string - DeptCode: - type: string - SiteID: - type: integer - responses: - '200': - description: Department updated - /api/organization/workstation: - get: - tags: - - Organization - summary: List workstations - security: - - bearerAuth: [] - responses: - '200': - description: List of workstations - post: - tags: - - Organization - summary: Create workstation - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Workstation' - responses: - '201': - description: Workstation created - delete: - tags: - - Organization - summary: Delete workstation - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - responses: - '200': - description: Workstation deleted - /api/organization/workstation/{id}: - get: - tags: - - Organization - summary: Get workstation by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Workstation details - patch: - tags: - - Organization - summary: Update workstation - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - WorkstationName: - type: string - WorkstationCode: - type: string - SiteID: - type: integer - DepartmentID: - type: integer - responses: - '200': - description: Workstation updated - /api/organization/hostapp: - get: - tags: - - Organization - summary: List host applications - security: - - bearerAuth: [] - parameters: - - name: HostAppID - in: query - schema: - type: string - - name: HostAppName - in: query - schema: - type: string - responses: - '200': - description: List of host applications - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/HostApp' - post: - tags: - - Organization - summary: Create host application - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/HostApp' - responses: - '201': - description: Host application created - delete: - tags: - - Organization - summary: Delete host application (soft delete) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - HostAppID - properties: - HostAppID: - type: string - responses: - '200': - description: Host application deleted - /api/organization/hostapp/{id}: - get: - tags: - - Organization - summary: Get host application by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '200': - description: Host application details - content: - application/json: - schema: - $ref: '#/components/schemas/HostApp' - patch: - tags: - - Organization - summary: Update host application - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - HostAppName: - type: string - SiteID: - type: integer - responses: - '200': - description: Host application updated - /api/organization/hostcompara: - get: - tags: - - Organization - summary: List host communication parameters - security: - - bearerAuth: [] - parameters: - - name: HostAppID - in: query - schema: - type: string - - name: HostIP - in: query - schema: - type: string - responses: - '200': - description: List of host communication parameters - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/HostComPara' - post: - tags: - - Organization - summary: Create host communication parameters - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/HostComPara' - responses: - '201': - description: Host communication parameters created - delete: - tags: - - Organization - summary: Delete host communication parameters (soft delete) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - HostAppID - properties: - HostAppID: - type: string - responses: - '200': - description: Host communication parameters deleted - /api/organization/hostcompara/{id}: - get: - tags: - - Organization - summary: Get host communication parameters by HostAppID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - '200': - description: Host communication parameters details - content: - application/json: - schema: - $ref: '#/components/schemas/HostComPara' - patch: - tags: - - Organization - summary: Update host communication parameters - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - HostIP: - type: string - HostPort: - type: string - HostPwd: - type: string - responses: - '200': - description: Host communication parameters updated - /api/organization/codingsys: - get: - tags: - - Organization - summary: List coding systems - security: - - bearerAuth: [] - parameters: - - name: CodingSysAbb - in: query - schema: - type: string - - name: FullText - in: query - schema: - type: string - responses: - '200': - description: List of coding systems - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/CodingSys' - post: - tags: - - Organization - summary: Create coding system - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CodingSys' - responses: - '201': - description: Coding system created - delete: - tags: - - Organization - summary: Delete coding system (soft delete) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - CodingSysID - properties: - CodingSysID: - type: integer - responses: - '200': - description: Coding system deleted - /api/organization/codingsys/{id}: - get: - tags: - - Organization - summary: Get coding system by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Coding system details - content: - application/json: - schema: - $ref: '#/components/schemas/CodingSys' - patch: - tags: - - Organization - summary: Update coding system - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - CodingSysAbb: - type: string - FullText: - type: string - Description: - type: string - responses: - '200': - description: Coding system updated - /api/patvisit: - get: - tags: - - Patient Visit - summary: List patient visits - security: - - bearerAuth: [] - parameters: - - name: InternalPID - in: query - schema: - type: integer - description: Filter by internal patient ID (exact match) - - name: PVID - in: query - schema: - type: string - description: Filter by visit ID (partial match) - - name: PatientID - in: query - schema: - type: string - description: Filter by patient ID (partial match) - - name: PatientName - in: query - schema: - type: string - description: Search by patient name (searches in both first and last name) - - name: CreateDateFrom - in: query - schema: - type: string - format: date-time - description: Filter visits created on or after this date - - name: CreateDateTo - in: query - schema: - type: string - format: date-time - description: Filter visits created on or before this date - - name: page - in: query - schema: - type: integer - - name: perPage - in: query - schema: - type: integer - responses: - '200': - description: List of patient visits - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/PatientVisit' - total: - type: integer - description: Total number of records - page: - type: integer - description: Current page number - per_page: - type: integer - description: Number of records per page - post: - tags: - - Patient Visit - summary: Create patient visit - description: | - Creates a new patient visit. PVID is auto-generated with 'DV' prefix if not provided. - Can optionally include PatDiag (diagnosis) and PatVisitADT (ADT information). - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - InternalPID - properties: - PVID: - type: string - description: Visit ID (auto-generated with DV prefix if not provided) - InternalPID: - type: integer - description: Patient ID (required) - EpisodeID: - type: string - description: Episode identifier - SiteID: - type: integer - description: Site reference - PatDiag: - type: object - description: Optional diagnosis information - properties: - DiagCode: - type: string - Diagnosis: - type: string - PatVisitADT: - type: object - description: Optional ADT information - properties: - ADTCode: - type: string - enum: - - A01 - - A02 - - A03 - - A04 - - A08 - LocationID: - type: integer - AttDoc: - type: integer - RefDoc: - type: integer - AdmDoc: - type: integer - CnsDoc: - type: integer - responses: - '201': - description: Visit created successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: object - properties: - PVID: - type: string - InternalPVID: - type: integer - delete: - tags: - - Patient Visit - summary: Delete patient visit - security: - - bearerAuth: [] - responses: - '200': - description: Visit deleted successfully - /api/patvisit/{id}: - get: - tags: - - Patient Visit - summary: Get visit by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - description: PVID (visit identifier like DV00001) - responses: - '200': - description: Visit details - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/PatientVisit' - patch: - tags: - - Patient Visit - summary: Update patient visit - description: | - Updates an existing patient visit. InternalPVID is required. - Can update main visit data, PatDiag, and add new PatVisitADT records. - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Internal visit ID (InternalPVID) - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - PVID: - type: string - InternalPID: - type: integer - EpisodeID: - type: string - SiteID: - type: integer - PatDiag: - type: object - description: Diagnosis information (will update if exists) - properties: - DiagCode: - type: string - Diagnosis: - type: string - PatVisitADT: - type: array - description: Array of ADT records to add (new records only) - items: - type: object - properties: - ADTCode: - type: string - enum: - - A01 - - A02 - - A03 - - A04 - - A08 - LocationID: - type: integer - AttDoc: - type: integer - RefDoc: - type: integer - AdmDoc: - type: integer - CnsDoc: - type: integer - sequence: - type: integer - description: Used for ordering multiple ADT records - responses: - '200': - description: Visit updated successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: object - properties: - PVID: - type: string - InternalPVID: - type: integer - /api/patvisit/patient/{patientId}: - get: - tags: - - Patient Visit - summary: Get visits by patient ID - security: - - bearerAuth: [] - parameters: - - name: patientId - in: path - required: true - schema: - type: integer - description: Internal Patient ID (InternalPID) - responses: - '200': - description: Patient visits list - content: - application/json: - schema: - type: object - properties: - status: - type: string - data: - type: array - items: - $ref: '#/components/schemas/PatientVisit' - /api/patvisitadt: - post: - tags: - - Patient Visit - summary: Create ADT record - description: Create a new Admission/Discharge/Transfer record - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PatVisitADT' - responses: - '201': - description: ADT record created successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - delete: - tags: - - Patient Visit - summary: Delete ADT visit (soft delete) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - PVADTID - properties: - PVADTID: - type: integer - description: ADT record ID to delete - responses: - '200': - description: ADT visit deleted successfully - /api/patvisitadt/visit/{visitId}: - get: - tags: - - Patient Visit - summary: Get ADT history by visit ID - description: Retrieve the complete Admission/Discharge/Transfer history for a visit, including all locations and doctors - security: - - bearerAuth: [] - parameters: - - name: visitId - in: path - required: true - schema: - type: integer - description: Internal Visit ID (InternalPVID) - responses: - '200': - description: ADT history retrieved successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: ADT history retrieved - data: - type: array - items: - type: object - properties: - PVADTID: - type: integer - InternalPVID: - type: integer - ADTCode: - type: string - enum: - - A01 - - A02 - - A03 - - A04 - - A08 - LocationID: - type: integer - LocationName: - type: string - AttDoc: - type: integer - AttDocFirstName: - type: string - AttDocLastName: - type: string - RefDoc: - type: integer - RefDocFirstName: - type: string - RefDocLastName: - type: string - AdmDoc: - type: integer - AdmDocFirstName: - type: string - AdmDocLastName: - type: string - CnsDoc: - type: integer - CnsDocFirstName: - type: string - CnsDocLastName: - type: string - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - /api/patvisitadt/{id}: - get: - tags: - - Patient Visit - summary: Get ADT record by ID - description: Retrieve a single ADT record by its ID, including location and doctor details - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: ADT record ID (PVADTID) - responses: - '200': - description: ADT record retrieved successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: ADT record retrieved - data: - type: object - properties: - PVADTID: - type: integer - InternalPVID: - type: integer - ADTCode: - type: string - enum: - - A01 - - A02 - - A03 - - A04 - - A08 - LocationID: - type: integer - LocationName: - type: string - AttDoc: - type: integer - AttDocFirstName: - type: string - AttDocLastName: - type: string - RefDoc: - type: integer - RefDocFirstName: - type: string - RefDocLastName: - type: string - AdmDoc: - type: integer - AdmDocFirstName: - type: string - AdmDocLastName: - type: string - CnsDoc: - type: integer - CnsDocFirstName: - type: string - CnsDocLastName: - type: string - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - patch: - tags: - - Patient Visit - summary: Update ADT record - description: Update an existing ADT record - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: ADT record ID (PVADTID) - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/PatVisitADT' - responses: - '200': - description: ADT record updated successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - /api/patient: - get: - tags: - - Patient - summary: List patients - security: - - bearerAuth: [] - parameters: - - name: page - in: query - schema: - type: integer - default: 1 - - name: perPage - in: query - schema: - type: integer - default: 20 - - name: InternalPID - in: query - schema: - type: integer - description: Filter by internal patient ID - - name: PatientID - in: query - schema: - type: string - description: Filter by patient ID - - name: Name - in: query - schema: - type: string - description: Search by patient name - - name: Birthdate - in: query - schema: - type: string - format: date - description: Filter by birthdate (YYYY-MM-DD) - responses: - '200': - description: List of patients - content: - application/json: - schema: - $ref: '#/components/schemas/PatientListResponse' - post: - tags: - - Patient - summary: Create new patient - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Patient' - responses: - '201': - description: Patient created successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - '422': - description: Validation error - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - delete: - tags: - - Patient - summary: Delete patient (soft delete) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - InternalPID - properties: - InternalPID: - type: integer - description: Internal patient record ID - responses: - '200': - description: Patient deleted successfully - /api/patient/check: - get: - tags: - - Patient - summary: Check if patient exists - security: - - bearerAuth: [] - parameters: - - name: PatientID - in: query - schema: - type: string - description: Patient ID to check - - name: 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: - - Patient - summary: Get patient by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Internal patient record ID - responses: - '200': - description: Patient details - content: - application/json: - schema: - type: object - properties: - status: - type: string - data: - $ref: '#/components/schemas/Patient' - patch: - tags: - - Patient - summary: Update patient - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Internal patient record ID - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Patient' - responses: - '200': - description: Patient updated successfully - /api/report/{orderID}: - get: - tags: - - Report - summary: Generate lab report - description: Generate an HTML lab report for a specific order. Returns HTML content that can be viewed in browser or printed to PDF. - security: - - bearerAuth: [] - parameters: - - name: orderID - in: path - required: true - schema: - type: integer - description: Internal Order ID - responses: - '200': - description: HTML lab report - content: - text/html: - schema: - type: string - description: HTML content of the lab report - '404': - description: Order or patient not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - '500': - description: Failed to generate report - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /api/result: - get: - tags: - - Result - summary: List results - description: Retrieve patient test results with optional filters by order or patient - security: - - bearerAuth: [] - parameters: - - name: order_id - in: query - schema: - type: integer - description: Filter by internal order ID - - name: patient_id - in: query - schema: - type: integer - description: Filter by internal patient ID (returns cumulative results) - - name: page - in: query - schema: - type: integer - default: 1 - description: Page number for pagination - - name: per_page - in: query - schema: - type: integer - default: 20 - description: Number of results per page - responses: - '200': - description: List of results - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: array - items: - type: object - properties: - ResultID: - type: integer - OrderID: - type: integer - TestSiteID: - type: integer - TestSiteCode: - type: string - Result: - type: string - nullable: true - ResultDateTime: - type: string - format: date-time - RefNumID: - type: integer - nullable: true - RefTxtID: - type: integer - nullable: true - CreateDate: - type: string - format: date-time - TestSiteName: - type: string - nullable: true - Unit1: - type: string - nullable: true - Unit2: - type: string - nullable: true - Low: - type: number - nullable: true - High: - type: number - nullable: true - LowSign: - type: string - nullable: true - HighSign: - type: string - nullable: true - RefDisplay: - type: string - nullable: true - /api/result/{id}: - get: - tags: - - Result - summary: Get result by ID - description: Retrieve a specific result entry with all related data - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Result ID - responses: - '200': - description: Result details - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: object - properties: - ResultID: - type: integer - SiteID: - type: integer - OrderID: - type: integer - InternalSID: - type: integer - SID: - type: string - SampleID: - type: string - TestSiteID: - type: integer - TestSiteCode: - type: string - AspCnt: - type: integer - Result: - type: string - nullable: true - SampleType: - type: string - nullable: true - ResultDateTime: - type: string - format: date-time - WorkstationID: - type: integer - nullable: true - EquipmentID: - type: integer - nullable: true - RefNumID: - type: integer - nullable: true - RefTxtID: - type: integer - nullable: true - CreateDate: - type: string - format: date-time - TestSiteName: - type: string - nullable: true - Unit1: - type: string - nullable: true - Unit2: - type: string - nullable: true - Low: - type: number - nullable: true - High: - type: number - nullable: true - LowSign: - type: string - nullable: true - HighSign: - type: string - nullable: true - RefDisplay: - type: string - nullable: true - OrderNumber: - type: string - nullable: true - InternalPID: - type: integer - '404': - description: Result not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - patch: - tags: - - Result - summary: Update result - description: Update a result value with automatic validation against reference ranges. Returns calculated flag (L/H) in response but does not store it. - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Result ID - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - Result: - type: string - description: The result value - RefNumID: - type: integer - description: Reference range ID to validate against - SampleType: - type: string - nullable: true - WorkstationID: - type: integer - nullable: true - EquipmentID: - type: integer - nullable: true - responses: - '200': - description: Result updated successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: object - properties: - result: - type: object - flag: - type: string - nullable: true - enum: - - L - - H - description: Calculated flag - L for Low, H for High, null for normal - '400': - description: Validation failed - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - '404': - description: Result not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - delete: - tags: - - Result - summary: Delete result - description: Soft delete a result entry by setting DelDate - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Result ID - responses: - '200': - description: Result deleted successfully - content: - application/json: - schema: - $ref: '#/components/schemas/SuccessResponse' - '404': - description: Result not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /api/rule: - get: - tags: - - Rule - summary: List rules - security: - - bearerAuth: [] - parameters: - - name: EventCode - in: query - schema: - type: string - description: Filter by event code - - name: TestSiteID - in: query - schema: - type: integer - description: Filter by TestSiteID (returns rules linked to this test). Rules are only returned when attached to tests. - - name: search - in: query - schema: - type: string - description: Search by rule code or name - responses: - '200': - description: List of rules - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/RuleDef' - post: - tags: - - Rule - summary: Create rule - description: | - Create a new rule. Rules must be linked to at least one test via TestSiteIDs. - A single rule can be linked to multiple tests. Rules are active only when attached to tests. - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - RuleCode: - type: string - example: AUTO_SET_RESULT - RuleName: - type: string - example: Automatically Set Result - Description: - type: string - EventCode: - type: string - example: test_created - TestSiteIDs: - type: array - items: - type: integer - description: Array of TestSiteIDs to link this rule to (required) - example: - - 1 - - 2 - - 3 - ConditionExpr: - type: string - nullable: true - description: Raw DSL expression. Compile it first and persist the compiled JSON in ConditionExprCompiled. - example: if(sex('M'); result_set(0.5); result_set(0.6)) - ConditionExprCompiled: - type: string - nullable: true - description: Compiled JSON payload from POST /api/rule/compile - required: - - RuleCode - - RuleName - - EventCode - - TestSiteIDs - responses: - '201': - description: Rule created - /api/rule/{id}: - get: - tags: - - Rule - summary: Get rule with linked tests - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: RuleID - responses: - '200': - description: Rule details with linked test sites - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/RuleWithDetails' - '404': - description: Rule not found - patch: - tags: - - Rule - summary: Update rule - description: | - Update a rule. TestSiteIDs can be provided to update which tests the rule is linked to. - Tests not in the new list will be unlinked, and new tests will be linked. - Rules are active only when attached to tests. - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: RuleID - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - RuleCode: - type: string - RuleName: - type: string - Description: - type: string - EventCode: - type: string - TestSiteIDs: - type: array - items: - type: integer - description: Array of TestSiteIDs to link this rule to - ConditionExpr: - type: string - nullable: true - responses: - '200': - description: Rule updated - '404': - description: Rule not found - delete: - tags: - - Rule - summary: Soft delete rule - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: RuleID - responses: - '200': - description: Rule deleted - '404': - description: Rule not found - /api/rule/validate: - post: - tags: - - Rule - summary: Validate/evaluate an expression - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - expr: - type: string - context: - type: object - additionalProperties: true - required: - - expr - responses: - '200': - description: Validation result - /api/rule/compile: - post: - tags: - - Rule - summary: Compile DSL expression to engine-compatible structure - description: | - Compile a DSL expression to the engine-compatible JSON structure. - Frontend calls this when user clicks "Compile" button. - Returns compiled structure that can be saved to ConditionExprCompiled field. - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - expr: - type: string - description: Raw DSL expression - example: if(sex('M'); result_set(0.5); result_set(0.6)) - required: - - expr - responses: - '200': - description: Compilation successful - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - data: - type: object - properties: - raw: - type: string - description: Original DSL expression - compiled: - type: object - description: Parsed structure with conditionExpr, valueExpr, then, else - conditionExprCompiled: - type: string - description: JSON string to save to ConditionExprCompiled field - '400': - description: Compilation failed (invalid syntax) - /api/specimen: - get: - tags: - - Specimen - summary: List specimens - security: - - bearerAuth: [] - responses: - '200': - description: List of specimens - post: - tags: - - Specimen - summary: Create specimen - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Specimen' - responses: - '201': - description: Specimen created - /api/specimen/{id}: - get: - tags: - - Specimen - summary: Get specimen by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Specimen details - patch: - tags: - - Specimen - summary: Update specimen - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Specimen ID (SID) - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Specimen' - responses: - '200': - description: Specimen updated - delete: - tags: - - Specimen - summary: Delete specimen (soft delete) - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Specimen ID (SID) - responses: - '200': - description: Specimen deleted successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: Specimen deleted successfully - data: - type: object - properties: - SID: - type: integer - '404': - description: Specimen not found - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: failed - message: - type: string - example: Specimen not found - data: - type: null - '500': - description: Server error - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: failed - message: - type: string - example: Failed to delete specimen - data: - type: null - /api/specimen/container: - get: - tags: - - Specimen - summary: List container definitions - security: - - bearerAuth: [] - responses: - '200': - description: List of container definitions - post: - tags: - - Specimen - summary: Create container definition - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ContainerDef' - responses: - '201': - description: Container definition created - /api/specimen/container/{id}: - get: - tags: - - Specimen - summary: Get container definition by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Container definition details - patch: - tags: - - Specimen - summary: Update container definition - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Container definition ID (ConDefID) - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ContainerDef' - responses: - '200': - description: Container definition updated - /api/specimen/containerdef: - get: - tags: - - Specimen - summary: List container definitions (alias) - security: - - bearerAuth: [] - responses: - '200': - description: List of container definitions - post: - tags: - - Specimen - summary: Create container definition (alias) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ContainerDef' - responses: - '201': - description: Container definition created - /api/specimen/containerdef/{id}: - patch: - tags: - - Specimen - summary: Update container definition (alias) - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Container definition ID (ConDefID) - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ContainerDef' - responses: - '200': - description: Container definition updated - /api/specimen/prep: - get: - tags: - - Specimen - summary: List specimen preparations - security: - - bearerAuth: [] - responses: - '200': - description: List of specimen preparations - post: - tags: - - Specimen - summary: Create specimen preparation - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/SpecimenPrep' - responses: - '201': - description: Specimen preparation created - /api/specimen/prep/{id}: - get: - tags: - - Specimen - summary: Get specimen preparation by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Specimen preparation details - patch: - tags: - - Specimen - summary: Update specimen preparation - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Specimen preparation ID (SpcPrpID) - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/SpecimenPrep' - responses: - '200': - description: Specimen preparation updated - /api/specimen/status: - get: - tags: - - Specimen - summary: List specimen statuses - security: - - bearerAuth: [] - responses: - '200': - description: List of specimen statuses - post: - tags: - - Specimen - summary: Create specimen status - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/SpecimenStatus' - responses: - '201': - description: Specimen status created - /api/specimen/status/{id}: - get: - tags: - - Specimen - summary: Get specimen status by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Specimen status details - patch: - tags: - - Specimen - summary: Update specimen status - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Specimen status ID (SpcStaID) - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/SpecimenStatus' - responses: - '200': - description: Specimen status updated - /api/specimen/collection: - get: - tags: - - Specimen - summary: List specimen collection methods - security: - - bearerAuth: [] - responses: - '200': - description: List of collection methods - post: - tags: - - Specimen - summary: Create specimen collection method - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/SpecimenCollection' - responses: - '201': - description: Collection method created - /api/specimen/collection/{id}: - get: - tags: - - Specimen - summary: Get specimen collection method by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Collection method details - patch: - tags: - - Specimen - summary: Update specimen collection method - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Specimen collection ID (SpcColID) - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/SpecimenCollection' - responses: - '200': - description: Collection method updated - /api/test/testmap: - get: - tags: - - Test - summary: List all test mappings - security: - - bearerAuth: [] - responses: - '200': - description: List of test mappings - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: array - items: - type: object - properties: - TestMapID: - type: integer - HostType: - type: string - HostID: - type: string - HostName: - type: string - ClientType: - type: string - ClientID: - type: string - ClientName: - type: string - post: - tags: - - Test - summary: Create test mapping (header only) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestCode: - type: string - description: Test Code (required) - maps to HostTestCode or ClientTestCode - 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: - - TestCode - responses: - '201': - description: Test mapping created - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: integer - description: Created TestMapID - delete: - tags: - - Test - summary: Soft delete test mapping (cascades to details) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestMapID: - type: integer - description: Test Map ID to delete (required) - required: - - TestMapID - responses: - '200': - description: Test mapping deleted successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: integer - description: Deleted TestMapID - '404': - description: Test mapping not found or already deleted - /api/test/testmap/{id}: - get: - tags: - - Test - summary: Get test mapping by ID with details - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Test Map ID - responses: - '200': - description: Test mapping details with nested detail records - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/TestMap' - '404': - description: Test mapping not found - patch: - tags: - - Test - summary: Update test mapping - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Test Map ID - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestCode: - type: string - description: Test Code - maps to HostTestCode or ClientTestCode - HostType: - type: string - HostID: - type: string - ClientType: - type: string - ClientID: - type: string - responses: - '200': - description: Test mapping updated - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: integer - description: Updated TestMapID - /api/test/testmap/by-testcode/{testCode}: - get: - tags: - - Test - summary: Get test mappings by test code with details - security: - - bearerAuth: [] - parameters: - - name: testCode - in: path - required: true - schema: - type: string - description: Test Code (matches HostTestCode or ClientTestCode) - responses: - '200': - description: List of test mappings with details for the test code - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/TestMap' - /api/test/testmap/detail: - get: - tags: - - Test - summary: List test mapping details - security: - - bearerAuth: [] - parameters: - - name: TestMapID - in: query - schema: - type: integer - description: Filter by TestMapID - responses: - '200': - description: List of test mapping details - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/TestMapDetail' - post: - tags: - - Test - summary: Create test mapping detail - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestMapID: - type: integer - description: Test Map ID (required) - HostTestCode: - type: string - HostTestName: - type: string - ConDefID: - type: integer - ClientTestCode: - type: string - ClientTestName: - type: string - required: - - TestMapID - responses: - '201': - description: Test mapping detail created - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: integer - description: Created TestMapDetailID - delete: - tags: - - Test - summary: Soft delete test mapping detail - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestMapDetailID: - type: integer - description: Test Map Detail ID to delete (required) - required: - - TestMapDetailID - responses: - '200': - description: Test mapping detail deleted - /api/test/testmap/detail/{id}: - get: - tags: - - Test - summary: Get test mapping detail by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Test Map Detail ID - responses: - '200': - description: Test mapping detail - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/TestMapDetail' - patch: - tags: - - Test - summary: Update test mapping detail - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Test Map Detail ID - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestMapID: - type: integer - HostTestCode: - type: string - HostTestName: - type: string - ConDefID: - type: integer - ClientTestCode: - type: string - ClientTestName: - type: string - responses: - '200': - description: Test mapping detail updated - /api/test/testmap/detail/by-testmap/{testMapID}: - get: - tags: - - Test - summary: Get test mapping details by test map ID - security: - - bearerAuth: [] - parameters: - - name: testMapID - in: path - required: true - schema: - type: integer - description: Test Map ID - responses: - '200': - description: List of test mapping details - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '#/components/schemas/TestMapDetail' - /api/test/testmap/detail/batch: - post: - tags: - - Test - summary: Batch create test mapping details - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: array - items: - type: object - properties: - TestMapID: - type: integer - HostTestCode: - type: string - HostTestName: - type: string - ConDefID: - type: integer - ClientTestCode: - type: string - ClientTestName: - type: string - responses: - '200': - description: Batch create results - patch: - tags: - - Test - summary: Batch update test mapping details - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: array - items: - type: object - properties: - TestMapDetailID: - type: integer - TestMapID: - type: integer - HostTestCode: - type: string - HostTestName: - type: string - ConDefID: - type: integer - ClientTestCode: - type: string - ClientTestName: - type: string - responses: - '200': - description: Batch update results - delete: - tags: - - Test - summary: Batch delete test mapping details - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: array - items: - type: integer - description: TestMapDetailIDs to delete - responses: - '200': - description: Batch delete results - /api/test: - get: - tags: - - Test - summary: List test definitions - security: - - bearerAuth: [] - parameters: - - name: page - in: query - schema: - type: integer - default: 1 - description: Page number for pagination - - name: perPage - in: query - schema: - type: integer - default: 20 - description: Number of items per page - - name: SiteID - in: query - schema: - type: integer - description: Filter by site ID - - name: TestType - in: query - schema: - type: string - enum: - - TEST - - PARAM - - CALC - - GROUP - - TITLE - description: Filter by test type - - name: 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: - - Test - summary: Create test definition - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - SiteID: - type: integer - description: Site ID (required) - TestSiteCode: - type: string - description: Test code (required) - TestSiteName: - type: string - description: Test name (required) - TestType: - type: string - enum: - - TEST - - PARAM - - CALC - - GROUP - - TITLE - description: Test type (required) - Description: - type: string - DisciplineID: - type: integer - DepartmentID: - type: integer - ResultType: - type: string - enum: - - NMRIC - - RANGE - - TEXT - - VSET - - NORES - RefType: - type: string - enum: - - RANGE - - THOLD - - VSET - - TEXT - - NOREF - VSet: - type: integer - ReqQty: - type: number - format: decimal - ReqQtyUnit: - type: string - Unit1: - type: string - Factor: - type: number - format: decimal - Unit2: - type: string - Decimal: - type: integer - CollReq: - type: string - Method: - type: string - ExpectedTAT: - type: integer - SeqScr: - type: integer - SeqRpt: - type: integer - IndentLeft: - type: integer - FontStyle: - type: string - VisibleScr: - type: integer - VisibleRpt: - type: integer - CountStat: - type: integer - details: - type: object - description: | - Type-specific details. For CALC and GROUP types, include members array. - - **Important**: Members must use `TestSiteID` (the actual test ID), NOT `Member` or `SeqScr`. - Invalid TestSiteIDs will result in a 400 error. - properties: - DisciplineID: - type: integer - DepartmentID: - type: integer - ResultType: - type: string - enum: - - NMRIC - - RANGE - - TEXT - - VSET - - NORES - RefType: - type: string - enum: - - RANGE - - THOLD - - VSET - - TEXT - - NOREF - FormulaCode: - type: string - description: Formula expression for CALC type (e.g., "{TBIL} - {DBIL}") - Unit1: - type: string - Factor: - type: number - Unit2: - type: string - Decimal: - type: integer - default: 2 - Method: - type: string - ExpectedTAT: - type: integer - members: - type: array - description: | - Array of member tests for CALC and GROUP types. - Each member object must contain `TestSiteID` (the actual test ID). - Do NOT use `Member` or `SeqScr` - these will be rejected with validation error. - items: - type: object - properties: - TestSiteID: - type: integer - description: The actual TestSiteID of the member test (required) - required: - - TestSiteID - refnum: - type: array - items: - type: object - reftxt: - type: array - items: - type: object - testmap: - type: array - items: - type: object - required: - - SiteID - - TestSiteCode - - TestSiteName - - TestType - examples: - TEST_no_ref: - summary: Technical test without reference or map - value: - SiteID: 1 - TestSiteCode: TEST_NREF - TestSiteName: Numeric Test - TestType: TEST - SeqScr: 500 - SeqRpt: 500 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - details: - DisciplineID: 2 - DepartmentID: 2 - Unit1: mg/dL - Method: CBC Analyzer - PARAM_no_ref: - summary: Parameter without reference or map - value: - SiteID: 1 - TestSiteCode: PARAM_NRF - TestSiteName: Clinical Parameter - TestType: PARAM - SeqScr: 10 - SeqRpt: 10 - VisibleScr: 1 - VisibleRpt: 0 - CountStat: 0 - details: - DisciplineID: 10 - DepartmentID: 0 - Unit1: cm - Method: Manual entry - TEST_range_single: - summary: Technical test with numeric range reference (single) - value: - SiteID: 1 - TestSiteCode: TEST_RANGE - TestSiteName: Glucose Range - TestType: TEST - SeqScr: 105 - SeqRpt: 105 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - details: - DisciplineID: 2 - DepartmentID: 2 - ResultType: NMRIC - RefType: RANGE - Unit1: mg/dL - Method: Hexokinase - refnum: - - NumRefType: NMRC - RangeType: REF - Sex: '2' - LowSign: GE - Low: 70 - HighSign: LE - High: 100 - AgeStart: 18 - AgeEnd: 99 - Flag: 'N' - TEST_range_multiple_map: - summary: Numeric reference with multiple ranges and test map - value: - SiteID: 1 - TestSiteCode: TEST_RMAP - TestSiteName: Glucose Panic Range - TestType: TEST - SeqScr: 110 - SeqRpt: 110 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - details: - DisciplineID: 2 - DepartmentID: 2 - ResultType: NMRIC - RefType: RANGE - Unit1: mg/dL - Method: Hexokinase - refnum: - - NumRefType: NMRC - RangeType: REF - Sex: '2' - LowSign: GE - Low: 70 - HighSign: LE - High: 100 - AgeStart: 18 - AgeEnd: 99 - Flag: 'N' - - NumRefType: NMRC - RangeType: REF - Sex: '1' - LowSign: '>' - Low: 75 - HighSign: < - High: 105 - AgeStart: 18 - AgeEnd: 99 - Flag: 'N' - testmap: - - HostType: SITE - HostID: '1' - ClientType: WST - ClientID: '1' - details: - - HostTestCode: GLU - HostTestName: Glucose - ConDefID: 1 - ClientTestCode: GLU_C - ClientTestName: Glucose Client - - HostTestCode: CREA - HostTestName: Creatinine - ConDefID: 2 - ClientTestCode: CREA_C - ClientTestName: Creatinine Client - - HostType: WST - HostID: '3' - ClientType: INST - ClientID: '2' - details: - - HostTestCode: HB - HostTestName: Hemoglobin - ConDefID: 3 - ClientTestCode: HB_C - ClientTestName: Hemoglobin Client - TEST_threshold: - summary: Technical test with threshold reference - value: - SiteID: 1 - TestSiteCode: TEST_THLD - TestSiteName: Sodium Threshold - TestType: TEST - SeqScr: 115 - SeqRpt: 115 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - details: - DisciplineID: 2 - DepartmentID: 2 - ResultType: NMRIC - RefType: THOLD - Unit1: mmol/L - Method: Auto Analyzer - refnum: - - NumRefType: THOLD - RangeType: PANIC - Sex: '2' - LowSign: LT - Low: 120 - AgeStart: 0 - AgeEnd: 125 - Flag: H - TEST_threshold_map: - summary: Threshold reference plus test map - value: - SiteID: 1 - TestSiteCode: TEST_TMAP - TestSiteName: Potassium Panic - TestType: TEST - SeqScr: 120 - SeqRpt: 120 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - details: - DisciplineID: 2 - DepartmentID: 2 - ResultType: NMRIC - RefType: THOLD - Unit1: mmol/L - Method: Auto Analyzer - refnum: - - NumRefType: THOLD - RangeType: PANIC - Sex: '2' - LowSign: LT - Low: 120 - AgeStart: 0 - AgeEnd: 125 - Flag: H - - NumRefType: THOLD - RangeType: PANIC - Sex: '1' - LowSign: < - Low: 121 - AgeStart: 0 - AgeEnd: 125 - Flag: H - testmap: - - HostType: SITE - HostID: '1' - ClientType: WST - ClientID: '1' - details: - - HostTestCode: HB - HostTestName: Hemoglobin - ConDefID: 3 - ClientTestCode: HB_C - ClientTestName: Hemoglobin Client - - HostTestCode: GLU - HostTestName: Glucose - ConDefID: 1 - ClientTestCode: GLU_C - ClientTestName: Glucose Client - TEST_text: - summary: Technical test with text reference - value: - SiteID: 1 - TestSiteCode: TEST_TEXT - TestSiteName: Disease Stage - TestType: TEST - SeqScr: 130 - SeqRpt: 130 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - details: - DisciplineID: 1 - DepartmentID: 1 - ResultType: TEXT - RefType: TEXT - Method: Morphology - reftxt: - - SpcType: GEN - TxtRefType: TEXT - Sex: '2' - AgeStart: 18 - AgeEnd: 99 - RefTxt: NORM=Normal;HIGH=High - Flag: 'N' - TEST_text_map: - summary: Text reference plus test map - value: - SiteID: 1 - TestSiteCode: TEST_TXM - TestSiteName: Disease Stage (Map) - TestType: TEST - SeqScr: 135 - SeqRpt: 135 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - details: - DisciplineID: 1 - DepartmentID: 1 - ResultType: TEXT - RefType: TEXT - reftxt: - - SpcType: GEN - TxtRefType: TEXT - Sex: '2' - AgeStart: 18 - AgeEnd: 99 - RefTxt: NORM=Normal - Flag: 'N' - - SpcType: GEN - TxtRefType: TEXT - Sex: '1' - AgeStart: 18 - AgeEnd: 99 - RefTxt: ABN=Abnormal - Flag: 'N' - testmap: - - HostType: SITE - HostID: '1' - ClientType: WST - ClientID: '1' - details: - - HostTestCode: STAGE - HostTestName: Disease Stage - ConDefID: 4 - ClientTestCode: STAGE_C - ClientTestName: Disease Stage Client - TEST_valueset: - summary: Technical test using a value set result - value: - SiteID: 1 - TestSiteCode: TEST_VSET - TestSiteName: Urine Color - TestType: TEST - SeqScr: 140 - SeqRpt: 140 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - details: - DisciplineID: 4 - DepartmentID: 4 - ResultType: VSET - RefType: VSET - Method: Visual - reftxt: - - SpcType: GEN - TxtRefType: VSET - Sex: '2' - AgeStart: 0 - AgeEnd: 120 - RefTxt: NORM=Normal;MACRO=Macro - Flag: 'N' - TEST_valueset_map: - summary: Value set reference with test map - value: - SiteID: 1 - TestSiteCode: TEST_VMAP - TestSiteName: Urine Color (Map) - TestType: TEST - SeqScr: 145 - SeqRpt: 145 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - details: - DisciplineID: 4 - DepartmentID: 4 - ResultType: VSET - RefType: VSET - reftxt: - - SpcType: GEN - TxtRefType: VSET - Sex: '2' - AgeStart: 0 - AgeEnd: 120 - RefTxt: NORM=Normal;ABN=Abnormal - Flag: 'N' - testmap: - - HostType: SITE - HostID: '1' - ClientType: WST - ClientID: '8' - details: - - HostTestCode: UCOLOR - HostTestName: Urine Color - ConDefID: 12 - ClientTestCode: UCOLOR_C - ClientTestName: Urine Color Client - TEST_valueset_map_no_reftxt: - summary: Value set result with mapping but without explicit text reference entries - value: - SiteID: 1 - TestSiteCode: TEST_VSETM - TestSiteName: Urine Result Map - TestType: TEST - SeqScr: 150 - SeqRpt: 150 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - details: - DisciplineID: 4 - DepartmentID: 4 - ResultType: VSET - RefType: VSET - testmap: - - HostType: SITE - HostID: '1' - ClientType: WST - ClientID: '8' - details: - - HostTestCode: UGLUC - HostTestName: Urine Glucose - ConDefID: 12 - ClientTestCode: UGLUC_C - ClientTestName: Urine Glucose Client - CALC_basic: - summary: Calculated test with members (no references) - value: - SiteID: 1 - TestSiteCode: CALC_BASE - TestSiteName: Estimated GFR - TestType: CALC - SeqScr: 190 - SeqRpt: 190 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 0 - details: - DisciplineID: 2 - DepartmentID: 2 - FormulaCode: CKD_EPI(CREA,AGE,GENDER) - members: - - TestSiteID: 21 - - TestSiteID: 22 - CALC_full: - summary: Calculated test with numeric reference ranges and map - value: - SiteID: 1 - TestSiteCode: CALC_FULL - TestSiteName: Estimated GFR (Map) - TestType: CALC - SeqScr: 195 - SeqRpt: 195 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 0 - details: - DisciplineID: 2 - DepartmentID: 2 - FormulaCode: CKD_EPI(CREA,AGE,GENDER) - members: - - TestSiteID: 21 - - TestSiteID: 22 - refnum: - - NumRefType: NMRC - RangeType: REF - Sex: '2' - LowSign: GE - Low: 10 - HighSign: LE - High: 20 - AgeStart: 18 - AgeEnd: 120 - Flag: 'N' - testmap: - - HostType: SITE - HostID: '1' - ClientType: WST - ClientID: '3' - details: - - HostTestCode: EGFR - HostTestName: eGFR - ConDefID: 1 - ClientTestCode: EGFR_C - ClientTestName: eGFR Client - GROUP_with_members: - summary: Group/profile test with members and mapping - value: - SiteID: 1 - TestSiteCode: GROUP_PNL - TestSiteName: Lipid Profile - TestType: GROUP - SeqScr: 10 - SeqRpt: 10 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 1 - details: - members: - - TestSiteID: 169 - - TestSiteID: 170 - testmap: - - HostType: SITE - HostID: '1' - ClientType: WST - ClientID: '3' - details: - - HostTestCode: LIPID - HostTestName: Lipid Profile - ConDefID: 1 - ClientTestCode: LIPID_C - ClientTestName: Lipid Client - responses: - '201': - description: Test definition created - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: created - message: - type: string - data: - type: object - properties: - TestSiteId: - type: integer - '400': - description: Validation error (e.g., invalid member TestSiteID) - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: failed - message: - type: string - example: 'Invalid member TestSiteID(s): 185, 186. Make sure to use TestSiteID, not SeqScr or other values.' - patch: - tags: - - Test - 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. For CALC and GROUP types, include members array. - - **Important**: Members must use `TestSiteID` (the actual test ID), NOT `Member` or `SeqScr`. - Invalid TestSiteIDs will result in a 400 error. - properties: - DisciplineID: - type: integer - DepartmentID: - type: integer - ResultType: - type: string - enum: - - NMRIC - - RANGE - - TEXT - - VSET - - NORES - RefType: - type: string - enum: - - RANGE - - THOLD - - VSET - - TEXT - - NOREF - FormulaCode: - type: string - description: Formula expression for CALC type (e.g., "{TBIL} - {DBIL}") - Unit1: - type: string - Factor: - type: number - Unit2: - type: string - Decimal: - type: integer - default: 2 - Method: - type: string - ExpectedTAT: - type: integer - members: - type: array - description: | - Array of member tests for CALC and GROUP types. - Each member object must contain `TestSiteID` (the actual test ID). - Do NOT use `Member` or `SeqScr` - these will be rejected with validation error. - items: - type: object - properties: - TestSiteID: - type: integer - description: The actual TestSiteID of the member test (required) - required: - - TestSiteID - 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 - '400': - description: Validation error (e.g., invalid member TestSiteID) - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: failed - message: - type: string - example: 'Invalid member TestSiteID(s): 185, 186. Make sure to use TestSiteID, not SeqScr or other values.' - /api/test/{id}: - get: - tags: - - Test - summary: Get test definition by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Test Site ID - responses: - '200': - description: Test definition details - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/TestDefinition' - '404': - description: Test not found - delete: - tags: - - Test - summary: Soft delete test definition - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Test Site ID to delete - requestBody: - content: - application/json: - schema: - type: object - properties: - TestSiteID: - type: integer - description: Optional - can be provided in body instead of path - responses: - '200': - description: Test disabled successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: object - properties: - TestSiteId: - type: integer - EndDate: - type: string - format: date-time - '404': - description: Test not found - '422': - description: Test already disabled - /api/user: - get: - tags: - - User - summary: List users with pagination and search - security: - - bearerAuth: [] - parameters: - - name: page - in: query - schema: - type: integer - default: 1 - description: Page number - - name: per_page - in: query - schema: - type: integer - default: 20 - description: Items per page - - name: search - in: query - schema: - type: string - description: Search term for username, email, or name - responses: - '200': - description: List of users with pagination - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: Users retrieved successfully - data: - type: object - properties: - users: - type: array - items: - $ref: '#/components/schemas/User' - pagination: - type: object - properties: - current_page: - type: integer - per_page: - type: integer - total: - type: integer - total_pages: - type: integer - '500': - description: Server error - post: - tags: - - User - summary: Create new user - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UserCreate' - responses: - '201': - description: User created successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: User created successfully - data: - type: object - properties: - UserID: - type: integer - Username: - type: string - Email: - type: string - '400': - description: Validation failed - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: failed - message: - type: string - example: Validation failed - data: - type: object - '500': - description: Server error - /api/user/{id}: - get: - tags: - - User - summary: Get user by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: User ID - responses: - '200': - description: User details - content: - application/json: - schema: - $ref: '#/components/schemas/User' - '404': - description: User not found - '500': - description: Server error - patch: - tags: - - User - summary: Update existing user - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: User ID - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UserUpdate' - responses: - '200': - description: User updated successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: User updated successfully - data: - type: object - properties: - UserID: - type: integer - updated_fields: - type: array - items: - type: string - '400': - description: UserID is required - '404': - description: User not found - '500': - description: Server error - delete: - tags: - - User - summary: Delete user (soft delete) - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: User ID - responses: - '200': - description: User deleted successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: User deleted successfully - data: - type: object - properties: - UserID: - type: integer - '404': - description: User not found - '500': - description: Server error - /api/valueset: - get: - tags: - - ValueSet - summary: List lib value sets - description: List all library/system value sets from JSON files with item counts. Returns an array of objects with value, label, and count properties. - security: - - bearerAuth: [] - parameters: - - name: search - in: query - schema: - type: string - description: Optional search term to filter value set names or labels - responses: - '200': - description: List of lib value sets with item counts - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - data: - type: array - items: - $ref: '#/components/schemas/ValueSetListItem' - example: - - value: sex - label: Sex - count: 3 - - value: marital_status - label: Marital Status - count: 6 - - value: order_status - label: Order Status - count: 6 - /api/valueset/{key}: - get: - tags: - - ValueSet - summary: Get lib value set by key - description: | - Get a specific library/system value set from JSON files. - - **Available value set keys:** - - `activity_result` - Activity Result - - `additive` - Additive - - `adt_event` - ADT Event - - `area_class` - Area Class - - `body_site` - Body Site - - `collection_method` - Collection Method - - `container_cap_color` - Container Cap Color - - `container_class` - Container Class - - `container_size` - Container Size - - `country` - Country - - `death_indicator` - Death Indicator - - `did_type` - DID Type - - `enable_disable` - Enable/Disable - - `entity_type` - Entity Type - - `ethnic` - Ethnic - - `fasting_status` - Fasting Status - - `formula_language` - Formula Language - - `generate_by` - Generate By - - `identifier_type` - Identifier Type - - `location_type` - Location Type - - `marital_status` - Marital Status - - `math_sign` - Math Sign - - `numeric_ref_type` - Numeric Reference Type - - `operation` - Operation (CRUD) - - `order_priority` - Order Priority - - `order_status` - Order Status - - `race` - Race (Ethnicity) - - `range_type` - Range Type - - `reference_type` - Reference Type - - `religion` - Religion - - `requested_entity` - Requested Entity - - `result_type` - Result Type - - `result_unit` - Result Unit - - `sex` - Sex - - `site_class` - Site Class - - `site_type` - Site Type - - `specimen_activity` - Specimen Activity - - `specimen_condition` - Specimen Condition - - `specimen_role` - Specimen Role - - `specimen_status` - Specimen Status - - `specimen_type` - Specimen Type - - `test_activity` - Test Activity - - `test_type` - Test Type - - `text_ref_type` - Text Reference Type - - `unit` - Unit - - `v_category` - VCategory - - `ws_type` - Workstation Type - security: - - bearerAuth: [] - parameters: - - name: key - in: path - required: true - schema: - type: string - enum: - - activity_result - - additive - - adt_event - - area_class - - body_site - - collection_method - - container_cap_color - - container_class - - container_size - - country - - death_indicator - - did_type - - enable_disable - - entity_type - - ethnic - - fasting_status - - formula_language - - generate_by - - identifier_type - - location_type - - marital_status - - math_sign - - numeric_ref_type - - operation - - order_priority - - order_status - - race - - range_type - - reference_type - - religion - - requested_entity - - result_type - - result_unit - - sex - - site_class - - site_type - - specimen_activity - - specimen_condition - - specimen_role - - specimen_status - - specimen_type - - test_activity - - test_type - - text_ref_type - - unit - - v_category - - ws_type - description: Value set key name - responses: - '200': - description: Lib value set details - content: - application/json: - schema: - type: object - properties: - status: - type: string - data: - type: array - items: - $ref: '#/components/schemas/ValueSetLibItem' - /api/valueset/refresh: - post: - tags: - - ValueSet - summary: Refresh lib ValueSet cache - description: Clear and reload the library/system ValueSet cache from JSON files. Call this after modifying JSON files in app/Libraries/Data/. - security: - - bearerAuth: [] - responses: - '200': - description: Lib ValueSet cache refreshed - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: Cache cleared - /api/valueset/user/items: - get: - tags: - - ValueSet - summary: List user value set items - description: List value set items from database (user-defined) - security: - - bearerAuth: [] - parameters: - - name: VSetID - in: query - schema: - type: integer - description: Filter by ValueSet ID - - name: search - in: query - schema: - type: string - description: Search term to filter by VValue, VDesc, or VSName - - name: param - in: query - schema: - type: string - description: Alternative search parameter (alias for search) - responses: - '200': - description: List of user value set items - content: - application/json: - schema: - type: object - properties: - status: - type: string - data: - type: array - items: - $ref: '#/components/schemas/ValueSetItem' - post: - tags: - - ValueSet - summary: Create user value set item - description: Create value set item in database (user-defined) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - VSetID - properties: - SiteID: - type: integer - description: Site reference (default 1) - VSetID: - type: integer - description: Reference to value set definition (required) - VOrder: - type: integer - description: Display order (default 0) - VValue: - type: string - description: The value code - VDesc: - type: string - description: The display description/label - responses: - '201': - description: User value set item created - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/ValueSetItem' - /api/valueset/user/items/{id}: - get: - tags: - - ValueSet - summary: Get user value set item by ID - description: Get value set item from database (user-defined) - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: User value set item details - content: - application/json: - schema: - type: object - properties: - status: - type: string - data: - $ref: '#/components/schemas/ValueSetItem' - put: - tags: - - ValueSet - summary: Update user value set item - description: Update value set item in database (user-defined) - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - SiteID: - type: integer - description: Site reference - VSetID: - type: integer - description: Reference to value set definition - VOrder: - type: integer - description: Display order - VValue: - type: string - description: The value code - VDesc: - type: string - description: The display description/label - responses: - '200': - description: User value set item updated - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/ValueSetItem' - delete: - tags: - - ValueSet - summary: Delete user value set item - description: Delete value set item from database (user-defined) - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: User value set item deleted - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - /api/valueset/user/def: - get: - tags: - - ValueSet - summary: List user value set definitions - description: List value set definitions from database (user-defined) - security: - - bearerAuth: [] - parameters: - - name: search - in: query - schema: - type: string - description: Optional search term to filter definitions - - name: page - in: query - schema: - type: integer - default: 1 - description: Page number for pagination - - name: limit - in: query - schema: - type: integer - default: 100 - description: Number of items per page - responses: - '200': - description: List of user value set definitions - content: - application/json: - schema: - type: object - properties: - status: - type: string - data: - type: array - items: - $ref: '#/components/schemas/ValueSetDef' - meta: - type: object - properties: - total: - type: integer - page: - type: integer - limit: - type: integer - post: - tags: - - ValueSet - summary: Create user value set definition - description: Create value set definition in database (user-defined) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - SiteID: - type: integer - description: Site reference (default 1) - VSName: - type: string - description: Value set name - VSDesc: - type: string - description: Value set description - responses: - '201': - description: User value set definition created - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/ValueSetDef' - /api/valueset/user/def/{id}: - get: - tags: - - ValueSet - summary: Get user value set definition by ID - description: Get value set definition from database (user-defined) - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: User value set definition details - content: - application/json: - schema: - type: object - properties: - status: - type: string - data: - $ref: '#/components/schemas/ValueSetDef' - put: - tags: - - ValueSet - summary: Update user value set definition - description: Update value set definition in database (user-defined) - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - SiteID: - type: integer - description: Site reference - VSName: - type: string - description: Value set name - VSDesc: - type: string - description: Value set description - responses: - '200': - description: User value set definition updated - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '#/components/schemas/ValueSetDef' - delete: - tags: - - ValueSet - summary: Delete user value set definition - description: Delete value set definition from database (user-defined) - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: User value set definition deleted - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - description: JWT token from login endpoint - cookieAuth: - type: apiKey - in: cookie - name: token - description: JWT token stored in HTTP-only cookie - schemas: - SuccessResponse: - type: object - properties: - status: - type: string - example: success - message: - type: string - code: - type: integer - example: 200 - ErrorResponse: - type: object - properties: - status: - type: string - example: error - message: - type: string - errors: - type: object - DashboardSummary: - type: object - properties: - pendingOrders: - type: integer - todayResults: - type: integer - criticalResults: - type: integer - activePatients: - type: integer - LoginRequest: - type: object - required: - - username - - password - properties: - username: - type: string - example: labuser01 - password: - type: string - format: password - example: secret123 - LoginResponse: - type: object - properties: - status: - type: string - example: success - code: - type: integer - example: 200 - message: - type: string - example: Login successful - RegisterRequest: - type: object - required: - - username - - password - - email - properties: - username: - type: string - password: - type: string - format: password - email: - type: string - format: email - full_name: - type: string - Patient: - type: object - required: - - PatientID - - Sex - - NameFirst - - Birthdate - properties: - PatientID: - type: string - maxLength: 30 - pattern: ^[A-Za-z0-9]+$ - description: Internal patient identifier - AlternatePID: - type: string - maxLength: 30 - pattern: ^[A-Za-z0-9]+$ - Prefix: - type: string - maxLength: 10 - enum: - - Mr - - Mrs - - Ms - - Dr - - Prof - Sex: - type: string - enum: - - '1' - - '2' - description: '1: Female, 2: Male' - NameFirst: - type: string - minLength: 1 - maxLength: 60 - pattern: ^[A-Za-z'\. ]+$ - NameMiddle: - type: string - minLength: 1 - maxLength: 60 - NameMaiden: - type: string - minLength: 1 - maxLength: 60 - NameLast: - type: string - minLength: 1 - maxLength: 60 - Suffix: - type: string - maxLength: 10 - Birthdate: - type: string - format: date-time - description: ISO 8601 UTC datetime - PlaceOfBirth: - type: string - maxLength: 100 - Citizenship: - type: string - maxLength: 100 - Street_1: - type: string - maxLength: 255 - Street_2: - type: string - maxLength: 255 - Street_3: - type: string - maxLength: 255 - ZIP: - type: string - maxLength: 10 - pattern: ^[0-9]+$ - Phone: - type: string - pattern: ^\+?[0-9]{8,15}$ - MobilePhone: - type: string - pattern: ^\+?[0-9]{8,15}$ - EmailAddress1: - type: string - format: email - maxLength: 100 - EmailAddress2: - type: string - format: email - maxLength: 100 - PatIdt: - $ref: '#/components/schemas/PatientIdentifier' - LinkTo: - type: array - description: Array of linked patient references - items: - $ref: '#/components/schemas/LinkedPatient' - Custodian: - $ref: '#/components/schemas/Custodian' - 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 - LastLocation: - type: string - description: Full name of the last/current location from patvisitadt - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - ArchivedDate: - type: string - format: date-time - DelDate: - type: string - format: date-time - PatDiag: - type: object - description: Diagnosis information (optional) - properties: - DiagCode: - type: string - Diagnosis: - type: string - PatVisitADT: - type: object - description: ADT (Admission/Discharge/Transfer) information (optional) - properties: - ADTCode: - type: string - enum: - - A01 - - A02 - - A03 - - A04 - - A08 - LocationID: - type: integer - AttDoc: - type: integer - description: Attending physician ContactID - RefDoc: - type: integer - description: Referring physician ContactID - AdmDoc: - type: integer - description: Admitting physician ContactID - CnsDoc: - type: integer - description: Consulting physician ContactID - PatVisitADT: - type: object - properties: - PVADTID: - type: integer - description: Primary key (auto-generated) - InternalPVID: - type: integer - description: Reference to patient visit - ADTCode: - type: string - enum: - - A01 - - A02 - - A03 - - A04 - - A08 - description: | - A01: Admit - A02: Transfer - A03: Discharge - A04: Register - A08: Update - LocationID: - type: integer - description: Location/ward reference - AttDoc: - type: integer - description: Attending physician ContactID - RefDoc: - type: integer - description: Referring physician ContactID - AdmDoc: - type: integer - description: Admitting physician ContactID - CnsDoc: - type: integer - description: Consulting physician ContactID - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - ArchivedDate: - type: string - format: date-time - DelDate: - type: string - format: date-time - Account: - type: object - properties: - id: - type: integer - AccountName: - type: string - AccountCode: - type: string - AccountType: - type: string - Site: - type: object - properties: - id: - type: integer - SiteName: - type: string - SiteCode: - type: string - maxLength: 2 - pattern: ^[A-Z0-9]{2}$ - AccountID: - type: integer - Discipline: - type: object - properties: - id: - type: integer - DisciplineName: - type: string - DisciplineCode: - type: string - SeqScr: - type: integer - description: Display order on screen - SeqRpt: - type: integer - description: Display order in reports - Department: - type: object - properties: - id: - type: integer - DeptName: - type: string - DeptCode: - type: string - SiteID: - type: integer - Workstation: - type: object - properties: - id: - type: integer - WorkstationName: - type: string - WorkstationCode: - type: string - SiteID: - type: integer - DepartmentID: - type: integer - HostApp: - type: object - properties: - HostAppID: - type: string - maxLength: 5 - HostAppName: - type: string - SiteID: - type: integer - SiteName: - type: string - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - HostComPara: - type: object - properties: - HostAppID: - type: string - maxLength: 5 - HostAppName: - type: string - HostIP: - type: string - maxLength: 15 - HostPort: - type: string - maxLength: 6 - HostPwd: - type: string - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - CodingSys: - type: object - properties: - CodingSysID: - type: integer - CodingSysAbb: - type: string - maxLength: 6 - FullText: - type: string - Description: - type: string - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - Specimen: - type: object - properties: - id: - type: integer - SpecimenID: - type: string - PatientID: - type: string - SpecimenType: - type: string - description: Specimen type code - SpecimenTypeLabel: - type: string - description: Specimen type display text - CollectionDate: - type: string - format: date-time - CollectionMethod: - type: string - description: Collection method code - CollectionMethodLabel: - type: string - description: Collection method display text - ContainerID: - type: integer - SpecimenStatus: - type: string - description: Specimen status code - SpecimenStatusLabel: - type: string - description: Specimen status display text - BodySite: - type: string - description: Body site code - BodySiteLabel: - type: string - description: Body site display text - ContainerDef: - type: object - properties: - id: - type: integer - ContainerCode: - type: string - ContainerName: - type: string - ConCategory: - type: string - description: Container category code - ConCategoryLabel: - type: string - description: Container category display text - ConSize: - type: string - description: Container size code - ConSizeLabel: - type: string - description: Container size display text - CapColor: - type: string - description: Cap color code - CapColorLabel: - type: string - description: Cap color display text - SpecimenPrep: - type: object - properties: - id: - type: integer - PrepCode: - type: string - PrepName: - type: string - Description: - type: string - SpecimenStatus: - type: object - properties: - id: - type: integer - StatusCode: - type: string - StatusName: - type: string - Description: - type: string - Status: - type: string - description: Status code - StatusLabel: - type: string - description: Status display text - Activity: - type: string - description: Activity code - ActivityLabel: - type: string - description: Activity display text - SpecimenCollection: - type: object - properties: - id: - type: integer - CollectionCode: - type: string - CollectionName: - type: string - Description: - type: string - CollectionMethod: - type: string - description: Collection method code - CollectionMethodLabel: - type: string - description: Collection method display text - Additive: - type: string - description: Additive code - AdditiveLabel: - type: string - description: Additive display text - SpecimenRole: - type: string - description: Specimen role code - SpecimenRoleLabel: - type: string - description: Specimen role display text - TestDefinition: - type: object - properties: - TestSiteID: - type: integer - SiteID: - type: integer - TestSiteCode: - type: string - TestSiteName: - type: string - TestType: - type: string - enum: - - TEST - - PARAM - - CALC - - GROUP - - TITLE - description: | - TEST: Technical test - PARAM: Parameter - CALC: Calculated - GROUP: Panel/Profile - TITLE: Section header - Description: - type: string - DisciplineID: - type: integer - DisciplineName: - type: string - DepartmentID: - type: integer - DepartmentName: - type: string - ResultType: - type: string - enum: - - NMRIC - - RANGE - - TEXT - - VSET - - NORES - description: | - Result type determines the format of test results: - - NMRIC: Single numeric value - - RANGE: Numeric range (min-max) - - TEXT: Free text result - - VSET: Value set/enum result - - NORES: No result (for GROUP and TITLE types) - - TestType to ResultType mapping: - - TEST: NMRIC | RANGE | TEXT | VSET - - PARAM: NMRIC | RANGE | TEXT | VSET - - CALC: NMRIC (calculated result is always numeric) - - GROUP: NORES (no result, container only) - - TITLE: NORES (no result, header only) - RefType: - type: string - enum: - - RANGE - - THOLD - - VSET - - TEXT - - NOREF - description: | - Reference type determines which reference range table to use: - - RANGE: Numeric reference range - - THOLD: Threshold/panic range - - VSET: Value set reference - - TEXT: Free text reference - - NOREF: No reference (for NORES result type) - - ResultType to RefType mapping: - - NMRIC: RANGE | THOLD → refnum table - - RANGE: RANGE | THOLD → refnum table - - VSET: VSET → reftxt table - - TEXT: TEXT → reftxt table - - NORES: NOREF → (no reference table) - VSet: - type: integer - description: Value set ID for VSET result type - ReqQty: - type: number - format: decimal - description: Required sample quantity - ReqQtyUnit: - type: string - description: Unit for required quantity - Unit1: - type: string - description: Primary unit - Factor: - type: number - format: decimal - description: Conversion factor - Unit2: - type: string - description: Secondary unit (after conversion) - Decimal: - type: integer - description: Number of decimal places - CollReq: - type: string - description: Collection requirements - Method: - type: string - description: Test method - ExpectedTAT: - type: integer - description: Expected turnaround time - SeqScr: - type: integer - description: Screen sequence - SeqRpt: - type: integer - description: Report sequence - IndentLeft: - type: integer - default: 0 - FontStyle: - type: string - 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 - Requestable: - type: integer - default: 1 - description: Flag indicating if test can be requested (1=yes, 0=no) - CreateDate: - type: string - format: date-time - StartDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - FormulaCode: - type: string - description: Formula expression for calculated tests - testdefcal: - type: array - description: Calculated test details (only for CALC type) - items: - type: object - testdefgrp: - type: array - description: | - Group members (for GROUP and CALC types). - When creating or updating, provide members in details.members array with TestSiteID field. - Do NOT use Member or SeqScr fields when creating/updating. - items: - type: object - properties: - TestGrpID: - type: integer - description: Group membership record ID - TestSiteID: - type: integer - description: Parent group TestSiteID - Member: - type: integer - description: | - Member TestSiteID (foreign key to testdefsite). - **Note**: This field is in the response. When creating/updating, use TestSiteID in details.members array instead. - TestSiteCode: - type: string - description: Member test code - TestSiteName: - type: string - description: Member test name - TestType: - type: string - description: Member test type - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - testmap: - type: array - description: 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 - FormulaCode: CKD_EPI(CREA,AGE,GENDER) - Unit1: mL/min/1.73m2 - Decimal: 0 - testdefgrp: - - TestSiteID: 21 - TestSiteCode: CREA - TestSiteName: Creatinine - TestType: TEST - - TestSiteID: 51 - TestSiteCode: AGE - TestSiteName: Age - TestType: PARAM - refnum: - - RefNumID: 5 - NumRefType: NMRC - NumRefTypeLabel: Numeric - RangeType: REF - RangeTypeLabel: Reference Range - Sex: '1' - SexLabel: Female - LowSign: GE - LowSignLabel: '>=' - HighSign: LE - HighSignLabel: <= - Low: 10 - High: 20 - AgeStart: 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 - TestSiteID: 6 - Member: 100 - MemberTestSiteID: 100 - TestSiteCode: CHOL - TestSiteName: Total Cholesterol - TestType: TEST - - TestGrpID: 2 - TestSiteID: 6 - Member: 101 - MemberTestSiteID: 101 - TestSiteCode: TG - TestSiteName: Triglycerides - TestType: TEST - TITLE: - summary: Section header - value: - TestSiteID: 7 - SiteID: 1 - TestSiteCode: CHEM_HEADER - TestSiteName: '--- CHEMISTRY ---' - TestType: TITLE - DisciplineID: 2 - DepartmentID: 2 - SeqScr: 100 - SeqRpt: 100 - VisibleScr: 1 - VisibleRpt: 1 - CountStat: 0 - TestMap: - type: object - properties: - TestMapID: - type: integer - HostType: - type: string - description: Host type code (e.g., SITE, WORKSTATION, INSTRUMENT) - HostID: - type: string - description: Host identifier - ClientType: - type: string - description: Client type code (e.g., SITE, WORKSTATION, INSTRUMENT) - ClientID: - type: string - description: Client identifier - HostName: - type: string - description: Resolved host name (from view) - ClientName: - type: string - description: Resolved client name (from view) - details: - type: array - description: Test mapping detail records - items: - $ref: '#/components/schemas/TestMapDetail' - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - description: Soft delete timestamp - OrderTestList: - type: object - properties: - InternalOID: - type: integer - description: Internal order ID - OrderID: - type: string - description: Order ID (e.g., 0025030300001) - PlacerID: - type: string - nullable: true - InternalPID: - type: integer - description: Patient internal ID - SiteID: - type: integer - PVADTID: - type: integer - description: Visit ADT ID - ReqApp: - type: string - nullable: true - Priority: - type: string - enum: - - R - - S - - U - description: | - R: Routine - S: Stat - U: Urgent - PriorityLabel: - type: string - description: Priority display text - TrnDate: - type: string - format: date-time - description: Transaction/Order date - EffDate: - type: string - format: date-time - description: Effective date - CreateDate: - type: string - format: date-time - OrderStatus: - type: string - enum: - - ORD - - SCH - - ANA - - VER - - REV - - REP - description: | - ORD: Ordered - SCH: Scheduled - ANA: Analysis - VER: Verified - REV: Reviewed - REP: Reported - OrderStatusLabel: - type: string - description: Order status display text - OrderTest: - type: object - properties: - InternalOID: - type: integer - description: Internal order ID - OrderID: - type: string - description: Order ID (e.g., 0025030300001) - PlacerID: - type: string - nullable: true - InternalPID: - type: integer - description: Patient internal ID - SiteID: - type: integer - PVADTID: - type: integer - description: Visit ADT ID - ReqApp: - type: string - nullable: true - Priority: - type: string - enum: - - R - - S - - U - description: | - R: Routine - S: Stat - U: Urgent - PriorityLabel: - type: string - description: Priority display text - TrnDate: - type: string - format: date-time - description: Transaction/Order date - EffDate: - type: string - format: date-time - description: Effective date - CreateDate: - type: string - format: date-time - OrderStatus: - type: string - enum: - - ORD - - SCH - - ANA - - VER - - REV - - REP - description: | - ORD: Ordered - SCH: Scheduled - ANA: Analysis - VER: Verified - REV: Reviewed - REP: Reported - OrderStatusLabel: - type: string - description: Order status display text - Specimens: - type: array - items: - $ref: '#/components/schemas/OrderSpecimen' - description: Associated specimens for this order - Tests: - type: array - items: - $ref: '#/components/schemas/OrderTestItem' - description: Test results (patres) for this order - OrderItem: - type: object - properties: - id: - type: integer - OrderID: - type: string - TestID: - type: integer - SpecimenID: - type: string - Status: - type: string - EdgeResultRequest: - type: object - required: - - sample_id - - instrument_id - properties: - sample_id: - type: string - description: Sample barcode/identifier - instrument_id: - type: string - description: Instrument identifier - patient_id: - type: string - description: Patient identifier (optional) - results: - type: array - items: - type: object - properties: - test_code: - type: string - result_value: - type: string - unit: - type: string - flags: - type: string - enum: - - H - - L - - 'N' - - A - description: H=High, L=Low, N=Normal, A=Abnormal - EdgeResultResponse: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: Result received and queued - data: - type: object - properties: - edge_res_id: - type: integer - sample_id: - type: string - instrument_id: - type: string - EdgeOrder: - type: object - properties: - OrderID: - type: string - PatientID: - type: string - SampleID: - type: string - Tests: - type: array - items: - type: object - properties: - TestCode: - type: string - TestName: - type: string - SpecimenType: - type: string - Priority: - type: string - DueDateTime: - type: string - format: date-time - ValueSetLibItem: - type: object - description: Library/system value set item from JSON files - properties: - value: - type: string - description: The value/key code - label: - type: string - description: The display label - ValueSetDef: - type: object - description: User-defined value set definition (from database) - properties: - VSetID: - type: integer - description: Primary key - SiteID: - type: integer - description: Site reference - VSName: - type: string - description: Value set name - VSDesc: - type: string - description: Value set description - CreateDate: - type: string - format: date-time - description: Creation timestamp - EndDate: - type: string - format: date-time - nullable: true - description: Soft delete timestamp - ItemCount: - type: integer - description: Number of items in this value set - ValueSetItem: - type: object - description: User-defined value set item (from database) - properties: - VID: - type: integer - description: Primary key - SiteID: - type: integer - description: Site reference - VSetID: - type: integer - description: Reference to value set definition - VOrder: - type: integer - description: Display order - VValue: - type: string - description: The value code - VDesc: - type: string - description: The display description/label - VCategory: - type: string - description: Category code - CreateDate: - type: string - format: date-time - description: Creation timestamp - EndDate: - type: string - format: date-time - nullable: true - description: Soft delete timestamp - VSName: - type: string - description: Value set name (from joined definition) - Location: - type: object - properties: - LocationID: - type: integer - description: Primary key - SiteID: - type: integer - description: Reference to site - LocCode: - type: string - maxLength: 6 - description: Location code (short identifier) - Parent: - type: integer - nullable: true - description: Parent location ID for hierarchical locations - LocFull: - type: string - maxLength: 255 - description: Full location name - Description: - type: string - maxLength: 255 - description: Location description - LocType: - type: string - description: Location type code (e.g., ROOM, WARD, BUILDING) - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - nullable: true - EquipmentList: - type: object - properties: - EID: - type: integer - description: Equipment ID (auto-increment) - IEID: - type: string - maxLength: 50 - description: Internal Equipment ID - DepartmentID: - type: integer - description: Reference to department - InstrumentID: - type: string - maxLength: 150 - description: Instrument identifier - InstrumentName: - type: string - maxLength: 150 - description: Instrument display name - WorkstationID: - type: integer - description: Reference to workstation - Enable: - type: integer - enum: - - 0 - - 1 - description: Equipment status (0=disabled, 1=enabled) - EquipmentRole: - type: string - maxLength: 1 - description: Equipment role code - CreateDate: - type: string - format: date-time - description: Creation timestamp - EndDate: - type: string - format: date-time - nullable: true - description: Deletion timestamp (soft delete) - DepartmentName: - type: string - description: Joined department name - WorkstationName: - type: string - description: Joined workstation name - User: - type: object - properties: - UserID: - type: integer - description: Unique user identifier - Username: - type: string - description: Unique login username - Email: - type: string - format: email - description: User email address - Name: - type: string - description: Full name of the user - Role: - type: string - description: User role (admin, technician, doctor, etc.) - Department: - type: string - description: Department name - IsActive: - type: boolean - description: Whether the user account is active - CreatedAt: - type: string - format: date-time - description: Creation timestamp - UpdatedAt: - type: string - format: date-time - description: Last update timestamp - DelDate: - type: string - format: date-time - nullable: true - description: Soft delete timestamp (null if active) - UserCreate: - type: object - required: - - Username - - Email - properties: - Username: - type: string - minLength: 3 - maxLength: 50 - description: Unique login username - Email: - type: string - format: email - maxLength: 100 - description: User email address - Name: - type: string - description: Full name of the user - Role: - type: string - description: User role - Department: - type: string - description: Department name - IsActive: - type: boolean - default: true - description: Whether the user account is active - UserUpdate: - type: object - required: - - UserID - properties: - UserID: - type: integer - description: User ID to update - Email: - type: string - format: email - description: User email address - Name: - type: string - description: Full name of the user - Role: - type: string - description: User role - Department: - type: string - description: Department name - IsActive: - type: boolean - description: Whether the user account is active - UserListResponse: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: Users retrieved successfully - data: - type: object - properties: - users: - type: array - items: - $ref: '#/components/schemas/User' - pagination: - type: object - properties: - current_page: - type: integer - per_page: - type: integer - total: - type: integer - total_pages: - type: integer - RuleDef: - type: object - properties: - RuleID: - type: integer - RuleCode: - type: string - example: AUTO_SET_RESULT - RuleName: - type: string - example: Automatically Set Result - Description: - type: string - nullable: true - EventCode: - type: string - example: ORDER_CREATED - ConditionExpr: - type: string - nullable: true - description: Raw DSL expression (editable) - example: if(sex('M'); result_set(0.5); result_set(0.6)) - ConditionExprCompiled: - type: string - nullable: true - description: Compiled JSON structure (auto-generated from ConditionExpr) - example: '{"conditionExpr":"patient[\"Sex\"] == \"M\"","valueExpr":"(patient[\"Sex\"] == \"M\") ? 0.5 : 0.6","then":[{"type":"RESULT_SET","value":0.5,"valueExpr":"0.5"}],"else":[{"type":"RESULT_SET","value":0.6,"valueExpr":"0.6"}]}' - CreateDate: - type: string - format: date-time - nullable: true - StartDate: - type: string - format: date-time - nullable: true - EndDate: - type: string - format: date-time - nullable: true - RuleWithDetails: - allOf: - - $ref: '#/components/schemas/RuleDef' - - type: object - properties: - linkedTests: - type: array - items: - type: integer - description: Array of TestSiteIDs this rule is linked to. Rules are active only when attached to tests. - TestRule: - type: object - description: Mapping between a rule and a test site (testrule table). Rules are active when linked via this table. - properties: - TestRuleID: - type: integer - RuleID: - type: integer - TestSiteID: - type: integer - CreateDate: - type: string - format: date-time - nullable: true - EndDate: - type: string - format: date-time - nullable: true - Contact: - type: object - properties: - ContactID: - type: integer - description: Primary key - NameFirst: - type: string - description: First name (required) - NameLast: - type: string - description: Last name - Title: - type: string - description: Title (e.g., Dr, Mr, Mrs) - Initial: - type: string - description: Middle initial - Birthdate: - type: string - format: date-time - description: Date of birth - EmailAddress1: - type: string - format: email - description: Primary email address - EmailAddress2: - type: string - format: email - description: Secondary email address - Phone: - type: string - description: Primary phone number - MobilePhone1: - type: string - description: Primary mobile number - MobilePhone2: - type: string - description: Secondary mobile number - Specialty: - type: string - description: Medical specialty code - SubSpecialty: - type: string - description: Sub-specialty code - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - description: Occupation display text - OrderSpecimen: - type: object - properties: - InternalSID: - type: integer - description: Internal specimen ID - SID: - type: string - description: Specimen ID (e.g., 0025030300001-S01) - SiteID: - type: integer - OrderID: - type: integer - description: Reference to internal order ID - ConDefID: - type: integer - description: Container Definition ID - nullable: true - ConCode: - type: string - description: Container code - nullable: true - ConName: - type: string - description: Container name - nullable: true - Qty: - type: integer - description: Quantity - Unit: - type: string - description: Unit of measurement - Status: - type: string - enum: - - PENDING - - COLLECTED - - RECEIVED - - PREPARED - - REJECTED - description: Current specimen status - GenerateBy: - type: string - description: Source that generated this specimen - CreateDate: - type: string - format: date-time - OrderTestItem: - type: object - properties: - ResultID: - type: integer - description: Unique result ID - OrderID: - type: integer - description: Reference to internal order ID - InternalSID: - type: integer - description: Reference to specimen - nullable: true - TestSiteID: - type: integer - description: Test definition site ID - TestSiteCode: - type: string - description: Test code - TestSiteName: - type: string - description: Test name - nullable: true - TestType: - type: string - description: Test type code identifying the test category - enum: - - TEST - - PARAM - - CALC - - GROUP - - TITLE - SID: - type: string - description: Order ID reference - SampleID: - type: string - description: Sample ID (same as OrderID) - SeqScr: - type: integer - nullable: true - description: Sequence number for this test on the screen - SeqRpt: - type: integer - nullable: true - description: Sequence number for this test in reports - Result: - type: string - description: Test result value - nullable: true - Discipline: - type: object - description: Discipline metadata used for ordering tests - properties: - DisciplineID: - type: integer - nullable: true - DisciplineCode: - type: string - nullable: true - DisciplineName: - type: string - nullable: true - SeqScr: - type: integer - nullable: true - description: Discipline sequence on the screen - SeqRpt: - type: integer - nullable: true - description: Discipline sequence in reports - ResultDateTime: - type: string - format: date-time - description: Result timestamp - CreateDate: - type: string - format: date-time - TestMapDetail: - type: object - properties: - TestMapDetailID: - type: integer - TestMapID: - type: integer - HostTestCode: - type: string - description: Test code in host system - HostTestName: - type: string - description: Test name in host system - ConDefID: - type: integer - description: Container definition ID - ClientTestCode: - type: string - description: Test code in client system - ClientTestName: - type: string - description: Test name in client system - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - description: Soft delete timestamp - 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/test-calc-engine.md b/docs/test-calc-engine.md deleted file mode 100644 index 94687a6..0000000 --- a/docs/test-calc-engine.md +++ /dev/null @@ -1,337 +0,0 @@ -# Calculator Service Operators Reference - -## Overview - -The `CalculatorService` (`app/Services/CalculatorService.php`) evaluates formulas with Symfony's `ExpressionLanguage`. This document lists the operators, functions, and constants that are available in the current implementation. - ---- - -## API Endpoints - -All endpoints live under `/api` and accept JSON. Responses use the standard `{ status, message, data }` envelope unless stated otherwise. - -### Calculate By Test Site - -Uses the `testdefcal` definition for a test site. The incoming body supplies the variables required by the formula. - -```http -POST /api/calc/testsite/123 -Content-Type: application/json - -{ - "result": 85, - "gender": "female", - "age": 30 -} -``` - -Response: - -```json -{ - "status": "success", - "data": { - "result": 92.4, - "testSiteID": 123, - "formula": "{result} * {factor} + {age}", - "variables": { - "result": 85, - "gender": "female", - "age": 30 - } - } -} -``` - -### Calculate By Code Or Name - -Evaluates a configured calculation by `TestSiteCode` or `TestSiteName`. Returns a compact map with a single key/value or `{}` on failure. - -```http -POST /api/calc/testcode/GLU -Content-Type: application/json - -{ - "result": 110, - "factor": 1.1 -} -``` - -Response: - -```json -{ - "GLU": 121 -} -``` - ---- - -## Supported Operators - -### Arithmetic Operators - -| Operator | Description | Example | Result | -|----------|-------------|---------|--------| -| `+` | Addition | `5 + 3` | `8` | -| `-` | Subtraction | `10 - 4` | `6` | -| `*` | Multiplication | `6 * 7` | `42` | -| `/` | Division | `20 / 4` | `5` | -| `%` | Modulo | `20 % 6` | `2` | -| `**` | Exponentiation (power) | `2 ** 3` | `8` | - -### Comparison Operators - -| Operator | Description | Example | -|----------|-------------|---------| -| `==` | Equal | `{result} == 10` | -| `!=` | Not equal | `{result} != 10` | -| `<` | Less than | `{result} < 10` | -| `<=` | Less than or equal | `{result} <= 10` | -| `>` | Greater than | `{result} > 10` | -| `>=` | Greater than or equal | `{result} >= 10` | - -### Logical Operators - -| Operator | Description | Example | -|----------|-------------|---------| -| `and` / `&&` | Logical AND | `{result} > 0 and {factor} > 0` | -| `or` / `||` | Logical OR | `{gender} == 1 or {gender} == 2` | -| `!` / `not` | Logical NOT | `not ({result} > 0)` | - -### Conditional Operators - -| Operator | Description | Example | -|----------|-------------|---------| -| `?:` | Ternary | `{result} > 10 ? {result} : 10` | -| `??` | Null coalescing | `{result} ?? 0` | - -### Parentheses - -Use parentheses to control operation precedence: - -``` -(2 + 3) * 4 // Result: 20 -2 + 3 * 4 // Result: 14 -``` - -### Notes - -- `^` is bitwise XOR (not exponentiation). Use `**` for powers. -- Variables must be numeric after normalization (gender is mapped to 0/1/2). - ---- - -## Functions - -Only the default ExpressionLanguage functions are available: - -| Function | Description | Example | -|----------|-------------|---------| -| `min(a, b, ...)` | Minimum value | `min({result}, 10)` | -| `max(a, b, ...)` | Maximum value | `max({result}, 10)` | -| `constant(name)` | PHP constant by name | `constant("PHP_INT_MAX")` | -| `enum(name)` | PHP enum case by name | `enum("App\\Enum\\Status::Active")` | - ---- - -## Constants - -ExpressionLanguage recognizes boolean and null literals: - -| Constant | Value | Description | -|----------|-------|-------------| -| `true` | `true` | Boolean true | -| `false` | `false` | Boolean false | -| `null` | `null` | Null value | - ---- - -## Variables in CalculatorService - -When using `calculateFromDefinition()`, the following variables are automatically available: - -| Variable | Description | Type | -|----------|-------------|------| -| `{result}` | The test result value | Float | -| `{factor}` | Calculation factor (default: 1) | Float | -| `{gender}` | Gender value (0=Unknown, 1=Female, 2=Male) | Integer | -| `{age}` | Patient age | Float | -| `{ref_low}` | Reference range low value | Float | -| `{ref_high}` | Reference range high value | Float | - -### Gender Mapping - -The `gender` variable accepts the following values: - -| Value | Description | -|-------|-------------| -| `0` | Unknown | -| `1` | Female | -| `2` | Male | - -Or use string values: `'unknown'`, `'female'`, `'male'` - ---- - -## Implicit Multiplication - -Implicit multiplication is not supported. Always use `*` between values: - -| Expression | Use Instead | -|------------|-------------| -| `2x` | `2 * x` | -| `{result}{factor}` | `{result} * {factor}` | - ---- - -## Usage Examples - -### Basic Calculation - -```php -use App\Services\CalculatorService; - -$calculator = new CalculatorService(); - -// Simple arithmetic -$result = $calculator->calculate("5 + 3 * 2"); -// Result: 11 - -// Using min/max -$result = $calculator->calculate("max({result}, 10)", ['result' => 7]); -// Result: 10 -``` - -### With Variables - -```php -$formula = "{result} * {factor} + 10"; -$variables = [ - 'result' => 5.2, - 'factor' => 2 -]; - -$result = $calculator->calculate($formula, $variables); -// Result: 20.4 -``` - -### BMI Calculation - -```php -$formula = "{weight} / ({height} ** 2)"; -$variables = [ - 'weight' => 70, // kg - 'height' => 1.75 // meters -]; - -$result = $calculator->calculate($formula, $variables); -// Result: 22.86 -``` - -### Gender-Based Calculation - -```php -// Apply different multipliers based on gender -$formula = "{result} * (1 + 0.1 * {gender})"; -$variables = [ - 'result' => 100, - 'gender' => 1 // Female = 1 -]; - -$result = $calculator->calculate($formula, $variables); -// Result: 110 -``` - -### Complex Formula - -```php -// Pythagorean theorem -$formula = "(({a} ** 2 + {b} ** 2) ** 0.5)"; -$variables = [ - 'a' => 3, - 'b' => 4 -]; - -$result = $calculator->calculate($formula, $variables); -// Result: 5 -``` - -### Using calculateFromDefinition - -```php -$calcDef = [ - 'FormulaCode' => '{result} * {factor} + {gender}', - 'Factor' => 2 -]; - -$testValues = [ - 'result' => 10, - 'gender' => 1 // Female -]; - -$result = $calculator->calculateFromDefinition($calcDef, $testValues); -// Result: 21 (10 * 2 + 1) -``` - ---- - -## Formula Validation - -Validate formulas before storing them: - -```php -$validation = $calculator->validate("{result} / {factor}"); -// Returns: ['valid' => true, 'error' => null] - -$validation = $calculator->validate("{result} /"); -// Returns: ['valid' => false, 'error' => 'Error message'] -``` - -### Extract Variables - -Get a list of variables used in a formula: - -```php -$variables = $calculator->extractVariables("{result} * {factor} + {age}"); -// Returns: ['result', 'factor', 'age'] -``` - ---- - -## Error Handling - -The service throws exceptions for invalid formulas or missing variables: - -```php -try { - $result = $calculator->calculate("{result} / 0"); -} catch (\Exception $e) { - // Handle division by zero or other errors - log_message('error', $e->getMessage()); -} -``` - -Common errors: - -- **Invalid formula syntax**: Malformed expressions -- **Missing variable**: Variable placeholder not provided in data array -- **Non-numeric value**: Variables must be numeric -- **Division by zero**: Mathematical error - ---- - -## Best Practices - -1. **Always validate formulas** before storing in database -2. **Use placeholder syntax** `{variable_name}` for clarity -3. **Handle exceptions** in production code -4. **Test edge cases** like zero values and boundary conditions -5. **Document formulas** with comments in your code - ---- - -## References - -- [Symfony ExpressionLanguage](https://symfony.com/doc/current/components/expression_language.html) -- `app/Services/CalculatorService.php` diff --git a/docs/test-rule-engine.md b/docs/test-rule-engine.md deleted file mode 100644 index 1762b0a..0000000 --- a/docs/test-rule-engine.md +++ /dev/null @@ -1,421 +0,0 @@ -# Test Rule Engine Documentation - -## Overview - -The CLQMS Rule Engine evaluates business rules that inspect orders, patients, and tests, then executes actions when the compiled condition matches. - -Rules are authored using a domain specific language stored in `ruledef.ConditionExpr`. Before the platform executes any rule, the DSL must be compiled into JSON and stored in `ConditionExprCompiled`, and each rule must be linked to the tests it should influence via `testrule`. - -### Execution Flow - -1. Write or edit the DSL in `ConditionExpr`. -2. POST the expression to `POST /api/rule/compile` to validate syntax and produce compiled JSON. -3. Save the compiled payload into `ConditionExprCompiled` and persist the rule in `ruledef`. -4. Link the rule to one or more tests through `testrule.TestSiteID` (rules only run for linked tests). -5. When the configured event fires (`test_created` or `result_updated`), the engine evaluates `ConditionExprCompiled` and runs the resulting `then` or `else` actions. - -> **Note:** The rule engine currently fires only for `test_created` and `result_updated`. Other event codes can exist in the database but are not triggered by the application unless additional `RuleEngineService::run(...)` calls are added. - -## Event Triggers - -| Event Code | Status | Trigger Point | -|------------|--------|----------------| -| `test_created` | Active | Fired after a new test row is persisted; the handler calls `RuleEngineService::run('test_created', ...)` to evaluate test-scoped rules | -| `result_updated` | Active | Fired whenever a test result is saved or updated so result-dependent rules run immediately | - -Other event codes remain in the database for future workflows, but only `test_created` and `result_updated` are executed by the current application flow. - -## Rule Structure - -``` -Rule -├── Event Trigger (when to run) -├── Conditions (when to match) -└── Actions (what to do) -``` - -The DSL expression lives in `ConditionExpr`. The compile endpoint (`/api/rule/compile`) renders the lifeblood of execution, producing `conditionExpr`, `valueExpr`, `then`, and `else` nodes that the engine consumes at runtime. - -## Syntax Guide - -### Basic Format - -``` -if(condition; then-action; else-action) -``` - -### Logical Operators - -- Use `&&` for AND (all sub-conditions must match). -- Use `||` for OR (any matching branch satisfies the rule). -- Surround mixed logic with parentheses for clarity and precedence. - -### Multi-Action Syntax - -Actions within any branch are separated by `:` and evaluated in order. Every `then` and `else` branch must end with an action; use `nothing` when no further work is required. - -``` -if(sex('M'); result_set(0.5):test_insert('HBA1C'); nothing) -``` - -### Multiple Rules - -Create each rule as its own `ruledef` row; do not chain expressions with commas. The `testrule` table manages rule-to-test mappings, so multiple rules can attach to the same test. Example: - -1. Insert `RULE_MALE_RESULT` and `RULE_SENIOR_COMMENT` in `ruledef`. -2. Add two `testrule` rows linking each rule to the appropriate `TestSiteID`. - -Each rule compiles and runs independently when its trigger fires and the test is linked. - -## Available Functions - -### Conditions - -| Function | Description | Example | -|----------|-------------|---------| -| `sex('M'|'F')` | Match patient sex | `sex('M')` | -| `priority('R'|'S'|'U')` | Match order priority | `priority('S')` | -| `age > 18` | Numeric age comparisons (`>`, `<`, `>=`, `<=`) | `age >= 18 && age <= 65` | -| `requested('CODE')` | Check whether the order already requested a test (queries `patres`) | `requested('GLU')` | - -### Logical Operators - -| Operator | Meaning | Example | -|----------|---------|---------| -| `&&` | AND (all truthy) | `sex('M') && age > 40` | -| `||` | OR (any truthy) | `sex('M') || age > 65` | -| `()` | Group expressions | `(sex('M') && age > 40) || priority('S')` | - -## Actions - -| Action | Description | Example | -|--------|-------------|---------| -| `result_set(value)` | (deprecated) Write to `patres.Result` for the current context test | `result_set(0.5)` | -| `result_set('CODE', value)` | Target a specific test by `TestSiteCode`, allowing multiple tests to be updated in one rule | `result_set('tesA', 0.5)` | -| `test_insert('CODE')` | Insert a test row by `TestSiteCode` if it doesn’t already exist for the order | `test_insert('HBA1C')` | -| `test_delete('CODE')` | Remove a previously requested test from the current order when the rule deems it unnecessary | `test_delete('INS')` | -| `comment_insert('text')` | Insert an order comment (`ordercom`) describing priority or clinical guidance | `comment_insert('Male patient - review')` | -| `nothing` | Explicit no-op to terminate an action chain | `nothing` | - -> **Note:** `set_priority()` was removed. Use `comment_insert()` for priority notes without altering billing. - -## Runtime Requirements - -1. **Compiled expression required:** Rules without `ConditionExprCompiled` are ignored (see `RuleEngineService::run`). -2. **Order context:** `context.order.InternalOID` must exist for any action that writes to `patres` or `ordercom`. -3. **TestSiteID:** `result_set()` needs `testSiteID` (either provided in context or from `order.TestSiteID`). When you provide a `TestSiteCode` as the first argument (`result_set('tesA', value)`), the engine resolves that code before writing the result. `test_insert()` resolves a `TestSiteID` via the `TestSiteCode` in `TestDefSiteModel`, and `test_delete()` removes the matching `TestSiteID` rows when needed. -4. **Requested check:** `requested('CODE')` inspects `patres` rows for the same `OrderID` and `TestSiteCode`. - -## Examples - -``` -if(sex('M'); result_set('tesA', 0.5):result_set('tesB', 1.2); result_set('tesA', 0.6):result_set('tesB', 1.0)) -``` -Sets both `tesA`/`tesB` results together per branch. - -``` -if(requested('GLU'); test_insert('HBA1C'):test_insert('INS'); nothing) -``` -Adds new tests when glucose is already requested. - -``` -if(sex('M') && age > 40; result_set(1.2); result_set(1.0)) -``` - -``` -if((sex('M') && age > 40) || (sex('F') && age > 50); result_set(1.5); result_set(1.0)) -``` - -``` -if(priority('S'); result_set('URGENT'):test_insert('STAT_TEST'); result_set('NORMAL')) -``` - -``` -if(sex('M') && age > 40; result_set(1.5):test_insert('EXTRA_TEST'):comment_insert('Male over 40'); nothing) -``` - -``` -if(sex('F') && (age >= 18 && age <= 50) && priority('S'); result_set('HIGH_PRIO'):comment_insert('Female stat 18-50'); result_set('NORMAL')) -``` - -``` -if(requested('GLU'); test_delete('INS'):comment_insert('Duplicate insulin request removed'); nothing) -``` - -## API Endpoints - -All endpoints live under `/api/rule` and accept JSON. Responses use the standard `{ status, message, data }` envelope. - -### List Rules - -```http -GET /api/rule?EventCode=test_created&TestSiteID=12&search=glucose -``` - -Query Params: - -- `EventCode` (optional) filter by event code. -- `TestSiteID` (optional) filter rules linked to a test site. -- `search` (optional) partial match against `RuleName`. - -Response: - -```json -{ - "status": "success", - "message": "fetch success", - "data": [ - { - "RuleID": 1, - "RuleCode": "RULE_001", - "RuleName": "Sex-based result", - "EventCode": "test_created", - "ConditionExpr": "if(sex('M'); result_set(0.5); result_set(0.6))", - "ConditionExprCompiled": "{...}" - } - ] -} -``` - -### Get Rule - -```http -GET /api/rule/1 -``` - -Response includes `linkedTests`: - -```json -{ - "status": "success", - "message": "fetch success", - "data": { - "RuleID": 1, - "RuleCode": "RULE_001", - "RuleName": "Sex-based result", - "EventCode": "test_created", - "ConditionExpr": "if(sex('M'); result_set(0.5); result_set(0.6))", - "ConditionExprCompiled": "{...}", - "linkedTests": [1, 2] - } -} -``` - -### Create Rule - -```http -POST /api/rule -Content-Type: application/json - -{ - "RuleCode": "RULE_001", - "RuleName": "Sex-based result", - "EventCode": "test_created", - "ConditionExpr": "if(sex('M'); result_set(0.5); result_set(0.6))", - "ConditionExprCompiled": "", - "TestSiteIDs": [1, 2] -} -``` - -Response: - -```json -{ - "status": "success", - "message": "Rule created successfully", - "data": { - "RuleID": 1 - } -} -``` - -### Update Rule - -```http -PATCH /api/rule/1 -Content-Type: application/json - -{ - "RuleName": "Sex-based result v2", - "ConditionExpr": "if(sex('M'); result_set(0.7); result_set(0.6))", - "ConditionExprCompiled": "", - "TestSiteIDs": [1, 3] -} -``` - -Response: - -```json -{ - "status": "success", - "message": "Rule updated successfully", - "data": { - "RuleID": 1 - } -} -``` - -### Delete Rule - -```http -DELETE /api/rule/1 -``` - -Response: - -```json -{ - "status": "success", - "message": "Rule deleted successfully", - "data": { - "RuleID": 1 - } -} -``` - -### Compile DSL - -Validates the DSL and returns a compiled JSON structure that should be persisted in `ConditionExprCompiled`. - -```http -POST /api/rule/compile -Content-Type: application/json - -{ - "expr": "if(sex('M'); result_set(0.5); result_set(0.6))" -} -``` - -Response: - -```json -{ - "status": "success", - "data": { - "raw": "if(sex('M'); result_set(0.5); result_set(0.6))", - "compiled": { - "conditionExpr": "sex('M')", - "then": ["result_set(0.5)"], - "else": ["result_set(0.6)"] - }, - "conditionExprCompiled": "{...}" - } -} -``` - -### Evaluate Expression (Validation) - -This endpoint evaluates an expression against a runtime context. It does not compile DSL or persist the result. - -```http -POST /api/rule/validate -Content-Type: application/json - -{ - "expr": "order[\"Age\"] > 18", - "context": { - "order": { - "Age": 25 - } - } -} -``` - -Response: - -```json -{ - "status": "success", - "data": { - "valid": true, - "result": true - } -} -``` - -## Database Schema - -### Tables - -- **ruledef** – stores rule metadata, raw DSL, and compiled JSON. -- **testrule** – mapping table that links rules to tests via `TestSiteID`. -- **ruleaction** – deprecated. Actions are now embedded in `ConditionExprCompiled`. - -### Key Columns - -| Column | Table | Description | -|--------|-------|-------------| -| `EventCode` | ruledef | The trigger event (typically `test_created` or `result_updated`). | -| `ConditionExpr` | ruledef | Raw DSL expression (semicolon syntax). | -| `ConditionExprCompiled` | ruledef | JSON payload consumed at runtime (`then`, `else`, etc.). | -| `ActionType` / `ActionParams` | ruleaction | Deprecated; actions live in compiled JSON now. | - -## Best Practices - -1. Always run `POST /api/rule/compile` before persisting a rule so `ConditionExprCompiled` exists. -2. Link each rule to the relevant tests via `testrule.TestSiteID`—rules are scoped to linked tests. -3. Use multi-action (`:`) to bundle several actions in a single branch; finish the branch with `nothing` if no further work is needed. -4. Prefer `comment_insert()` over the removed `set_priority()` action when documenting priority decisions. -5. Group complex boolean logic with parentheses for clarity when mixing `&&` and `||`. -6. Use `requested('CODE')` responsibly; it performs a database lookup on `patres` so avoid invoking it in high-frequency loops without reason. - -## Migration Guide - -### Syntax Changes (v2.0) - -The DSL moved from ternary (`condition ? action : action`) to semicolon syntax. Existing rules must be migrated via the provided script. - -| Old Syntax | New Syntax | -|------------|------------| -| `if(condition ? action : action)` | `if(condition; action; action)` | - -#### Migration Examples - -``` -# BEFORE -if(sex('M') ? result_set(0.5) : result_set(0.6)) - -# AFTER -if(sex('M'); result_set(0.5); result_set(0.6)) -``` - -``` -# BEFORE -if(sex('F') ? set_priority('S') : nothing) - -# AFTER -if(sex('F'); comment_insert('Female patient - review priority'); nothing) -``` - -#### Migration Process - -Run the migration which: - -1. Converts ternary syntax to semicolon syntax. -2. Recompiles every expression into JSON so the engine consumes `ConditionExprCompiled` directly. -3. Eliminates reliance on the `ruleaction` table. - -```bash -php spark migrate -``` - -## Troubleshooting - -### Rule Not Executing - -1. Ensure the rule has a compiled payload (`ConditionExprCompiled`). -2. Confirm the rule is linked to the relevant `TestSiteID` in `testrule`. -3. Verify the `EventCode` matches the currently triggered event (`test_created` or `result_updated`). -4. Check that `EndDate IS NULL` for both `ruledef` and `testrule` (soft deletes disable execution). -5. Use `/api/rule/compile` to validate the DSL and view errors. - -### Invalid Expression - -1. POST the expression to `/api/rule/compile` to get a detailed compilation error. -2. If using `/api/rule/validate`, supply the expected `context` payload; the endpoint simply evaluates the expression without saving it. - -### Runtime Errors - -- `RESULT_SET requires context.order.InternalOID` or `testSiteID`: include those fields in the context passed to `RuleEngineService::run()`. -- `TEST_INSERT` failures mean the provided `TestSiteCode` does not exist or the rule attempted to insert a duplicate test; check `testdefsite` and existing `patres` rows. -- `COMMENT_INSERT requires comment`: ensure the action provides text. diff --git a/src/lib/api/equipment.js b/src/lib/api/equipment.js index 89cfc07..e23bbf1 100644 --- a/src/lib/api/equipment.js +++ b/src/lib/api/equipment.js @@ -7,7 +7,7 @@ import { get, post, patch, del } from './client.js'; * @param {string} [params.InstrumentName] - Filter by instrument name * @param {number} [params.DepartmentID] - Filter by department ID * @param {number} [params.WorkstationID] - Filter by workstation ID - * @param {number} [params.Enable] - Filter by enable status (0 or 1) + * @param {number} [params.isEnable] - Filter by enable status (0 or 1) * @returns {Promise} List of equipment */ export async function fetchEquipmentList(params = {}) { @@ -29,7 +29,7 @@ export async function fetchEquipment(id) { * @param {Object} data - Equipment data * @param {string} data.IEID - Internal Equipment ID (required) * @param {number} data.DepartmentID - Department ID (required) - * @param {number} data.Enable - Enable status 0 or 1 (required) + * @param {number} data.isEnable - Enable status 0 or 1 (required) * @param {string} data.EquipmentRole - Equipment role code (required) * @param {string} [data.InstrumentID] - Instrument identifier * @param {string} [data.InstrumentName] - Instrument display name @@ -40,7 +40,7 @@ export async function createEquipment(data) { const payload = { IEID: data.IEID, DepartmentID: data.DepartmentID, - Enable: data.Enable, + isEnable: data.isEnable, EquipmentRole: data.EquipmentRole, InstrumentID: data.InstrumentID || null, InstrumentName: data.InstrumentName || null, @@ -55,7 +55,7 @@ export async function createEquipment(data) { * @param {number} data.EID - Equipment ID (required) * @param {string} [data.IEID] - Internal Equipment ID * @param {number} [data.DepartmentID] - Department ID - * @param {number} [data.Enable] - Enable status 0 or 1 + * @param {number} [data.isEnable] - Enable status 0 or 1 * @param {string} [data.EquipmentRole] - Equipment role code * @param {string} [data.InstrumentID] - Instrument identifier * @param {string} [data.InstrumentName] - Instrument display name @@ -66,7 +66,7 @@ export async function updateEquipment(id, data) { const payload = { IEID: data.IEID, DepartmentID: data.DepartmentID, - Enable: data.Enable, + isEnable: data.isEnable, EquipmentRole: data.EquipmentRole, InstrumentID: data.InstrumentID || null, InstrumentName: data.InstrumentName || null, diff --git a/src/lib/api/organization.js b/src/lib/api/organization.js index 6983c8c..8718ec3 100644 --- a/src/lib/api/organization.js +++ b/src/lib/api/organization.js @@ -246,6 +246,7 @@ export async function createWorkstation(data) { WorkstationName: data.WorkstationName, SiteID: data.SiteID, DepartmentID: data.DepartmentID, + isEnable: data.isEnable, }; return post('/api/organization/workstation', payload); } @@ -256,6 +257,7 @@ export async function updateWorkstation(id, data) { WorkstationName: data.WorkstationName, SiteID: data.SiteID, DepartmentID: data.DepartmentID, + isEnable: data.isEnable, }; return patch(`/api/organization/workstation/${id}`, payload); } diff --git a/src/lib/api/patients.js b/src/lib/api/patients.js index 75c4732..3933f94 100644 --- a/src/lib/api/patients.js +++ b/src/lib/api/patients.js @@ -70,7 +70,7 @@ export async function checkPatientExists(params = {}) { * @param {string} [data.MaritalStatus] - Marital status (A, B, D, M, S, W) * @param {string} [data.Religion] - Religion * @param {string} [data.Ethnic] - Ethnicity - * @param {string} [data.DeathIndicator] - Death indicator (Y/N) + * @param {number} [data.isDead] - Death indicator (0 or 1) * @param {string} [data.TimeOfDeath] - Time of death * @param {string} [data.PatCom] - Patient comments * @returns {Promise} API response diff --git a/src/lib/api/tests.js b/src/lib/api/tests.js index 5a15b71..a1b97a8 100644 --- a/src/lib/api/tests.js +++ b/src/lib/api/tests.js @@ -49,10 +49,10 @@ function buildPayload(formData, isUpdate = false) { Description: formData.Description, SeqScr: parseInt(formData.SeqScr) || 0, SeqRpt: parseInt(formData.SeqRpt) || 0, - VisibleScr: formData.VisibleScr ? 1 : 0, - VisibleRpt: formData.VisibleRpt ? 1 : 0, - CountStat: formData.CountStat ? 1 : 0, - Requestable: formData.Requestable ? 1 : 0, + isVisibleScr: formData.isVisibleScr ? 1 : 0, + isVisibleRpt: formData.isVisibleRpt ? 1 : 0, + isCountStat: formData.isCountStat ? 1 : 0, + isRequestable: formData.isRequestable ? 1 : 0, // StartDate is auto-set by backend (created_at) details: {}, refnum: [], diff --git a/src/lib/types/test.types.ts b/src/lib/types/test.types.ts index eaf68aa..aa8ea9e 100644 --- a/src/lib/types/test.types.ts +++ b/src/lib/types/test.types.ts @@ -22,9 +22,9 @@ export interface TestSummary { TestTypeLabel: string; SeqScr: number; SeqRpt: number; - VisibleScr: number | string; - VisibleRpt: number | string; - CountStat: number; + isVisibleScr: number | string; + isVisibleRpt: number | string; + isCountStat: number; StartDate: string; EndDate?: string; DisciplineID?: number; @@ -130,9 +130,9 @@ export interface TestDetail { SiteID: number; SeqScr: number; SeqRpt: number; - VisibleScr: number | string | boolean; - VisibleRpt: number | string | boolean; - CountStat: number | boolean; + isVisibleScr: number | string | boolean; + isVisibleRpt: number | string | boolean; + isCountStat: number | boolean; StartDate?: string; EndDate?: string; @@ -173,9 +173,9 @@ export interface CreateTestPayload { Description?: string; SeqScr?: number; SeqRpt?: number; - VisibleScr?: number | boolean; - VisibleRpt?: number | boolean; - CountStat?: number | boolean; + isVisibleScr?: number | boolean; + isVisibleRpt?: number | boolean; + isCountStat?: number | boolean; StartDate?: string; // Nested details based on TestType @@ -226,9 +226,9 @@ export interface TestFormState { SiteID: number; SeqScr: number; SeqRpt: number; - VisibleScr: boolean; - VisibleRpt: boolean; - CountStat: boolean; + isVisibleScr: boolean; + isVisibleRpt: boolean; + isCountStat: boolean; StartDate?: string; details: { DisciplineID?: number; @@ -296,7 +296,7 @@ export interface DeleteTestResponse extends ApiResponse<{ TestSiteId: number; En // Filter Options export interface TestFilterOptions { TestType?: TestType; - VisibleScr?: number; - VisibleRpt?: number; + isVisibleScr?: number; + isVisibleRpt?: number; search?: string; } diff --git a/src/routes/(app)/master-data/organization/instrument/+page.svelte b/src/routes/(app)/master-data/organization/instrument/+page.svelte index b71018b..decf7b6 100644 --- a/src/routes/(app)/master-data/organization/instrument/+page.svelte +++ b/src/routes/(app)/master-data/organization/instrument/+page.svelte @@ -26,7 +26,7 @@ InstrumentName: '', DepartmentID: null, WorkstationID: null, - Enable: 1, + isEnable: 1, EquipmentRole: '', }); let deleteConfirmOpen = $state(false); @@ -38,7 +38,7 @@ { key: 'IEID', label: 'IEID', class: 'font-medium' }, { key: 'InstrumentName', label: 'Name' }, { key: 'DepartmentName', label: 'Department' }, - { key: 'Enable', label: 'Status', class: 'w-24 text-center' }, + { key: 'isEnable', label: 'Status', class: 'w-24 text-center' }, { key: 'actions', label: 'Actions', class: 'w-32 text-center' }, ]; @@ -90,7 +90,7 @@ InstrumentName: '', DepartmentID: departments.length > 0 ? departments[0].DepartmentID : null, WorkstationID: null, - Enable: 1, + isEnable: 1, EquipmentRole: '', }; modalOpen = true; @@ -105,7 +105,7 @@ InstrumentName: row.InstrumentName || '', DepartmentID: row.DepartmentID, WorkstationID: row.WorkstationID, - Enable: row.Enable ?? 1, + isEnable: row.isEnable ?? 1, EquipmentRole: row.EquipmentRole || '', }; modalOpen = true; @@ -251,8 +251,8 @@ - {:else if column.key === 'Enable'} - {@html getStatusBadge(row.Enable)} + {:else if column.key === 'isEnable'} + {@html getStatusBadge(row.isEnable)} {:else} {row[column.key] || '-'} {/if} diff --git a/src/routes/(app)/master-data/organization/instrument/EquipmentModal.svelte b/src/routes/(app)/master-data/organization/instrument/EquipmentModal.svelte index 606d319..e90eda6 100644 --- a/src/routes/(app)/master-data/organization/instrument/EquipmentModal.svelte +++ b/src/routes/(app)/master-data/organization/instrument/EquipmentModal.svelte @@ -11,7 +11,7 @@ InstrumentName: '', DepartmentID: null, WorkstationID: null, - Enable: 1, + isEnable: 1, EquipmentRole: '', }), departments = [], @@ -134,7 +134,7 @@ + + + + Whether this workstation is active + {#snippet footer()} diff --git a/src/routes/(app)/master-data/tests/+page.svelte b/src/routes/(app)/master-data/tests/+page.svelte index d889964..3f6ab3c 100644 --- a/src/routes/(app)/master-data/tests/+page.svelte +++ b/src/routes/(app)/master-data/tests/+page.svelte @@ -326,19 +326,21 @@ hover={true} bordered={false} > - {#snippet cell({ column, row, value })} - {@const typeConfig = getTestTypeConfig(row.TestType)} - {@const IconComponent = typeConfig.icon} - {#if column.key === 'TestType'} - - - {typeConfig.label} - - {:else if column.key === 'Visible'} -
- S - R -
+ {#snippet cell({ column, row, value })} + {@const typeConfig = getTestTypeConfig(row.TestType)} + {@const IconComponent = typeConfig.icon} + {#if column.key === 'TestType'} + + + {typeConfig.label} + + {:else if column.key === 'Visible'} + {@const isVisibleScrActive = row.isVisibleScr === 1 || row.isVisibleScr === '1' || row.isVisibleScr === true} + {@const isVisibleRptActive = row.isVisibleRpt === 1 || row.isVisibleRpt === '1' || row.isVisibleRpt === true} +
+ S + R +
{:else if column.key === 'actions'}
+ bind:value={formData.Citizenship} + placeholder="Enter citizenship" + /> +
+ + +
+ {/if}