From afd8028a21ffd9b49756f3e3627ff400bc2831de Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Wed, 4 Mar 2026 16:48:03 +0700 Subject: [PATCH] feat(reports,results): add complete reports and results management modules Add new Reports module: - Create reports page with listing and viewer functionality - Add ReportViewerModal for viewing generated reports - Implement reports API client with endpoints Add new Results module: - Create results page for lab result entry and management - Add ResultEntryModal for entering test results - Implement results API client with validation support API and Store Updates: - Update auth.js API client with improved error handling - Enhance client.js with new request utilities - Update auth store for better session management UI/UX Improvements: - Update dashboard page layout and styling - Enhance OrderFormModal with better test selection - Improve login page styling and validation - Update main app layout with new navigation items Documentation: - Add bundled API documentation (api-docs.bundled.yaml) - Remove outdated component organization docs - Delete deprecated YAML specification files Cleanup: - Remove cookies.txt from tracking - Delete COMPONENT_ORGANIZATION.md - Consolidate documentation files --- COMPONENT_ORGANIZATION.md | 155 - cookies.txt | 5 + docs/api-docs.bundled.yaml | 6451 +++++++++++++++++ docs/clqms_database.dbml | 640 -- docs/orders.yaml | 265 - docs/organization.yaml | 707 -- docs/patient-visits.yaml | 519 -- docs/testmap.yaml | 503 -- docs/use_case_260214.md | 514 -- src/lib/api/auth.js | 4 +- src/lib/api/client.js | 14 +- src/lib/api/reports.js | 44 + src/lib/api/results.js | 75 + src/lib/stores/auth.js | 84 +- src/routes/(app)/+layout.svelte | 17 +- src/routes/(app)/dashboard/+page.svelte | 330 +- src/routes/(app)/orders/OrderFormModal.svelte | 155 +- src/routes/(app)/reports/+page.svelte | 311 + .../(app)/reports/ReportViewerModal.svelte | 137 + src/routes/(app)/results/+page.svelte | 287 + .../(app)/results/ResultEntryModal.svelte | 301 + src/routes/login/+page.svelte | 10 +- 22 files changed, 8061 insertions(+), 3467 deletions(-) delete mode 100644 COMPONENT_ORGANIZATION.md create mode 100644 cookies.txt create mode 100644 docs/api-docs.bundled.yaml delete mode 100644 docs/clqms_database.dbml delete mode 100644 docs/orders.yaml delete mode 100644 docs/organization.yaml delete mode 100644 docs/patient-visits.yaml delete mode 100644 docs/testmap.yaml delete mode 100644 docs/use_case_260214.md create mode 100644 src/lib/api/reports.js create mode 100644 src/lib/api/results.js create mode 100644 src/routes/(app)/reports/+page.svelte create mode 100644 src/routes/(app)/reports/ReportViewerModal.svelte create mode 100644 src/routes/(app)/results/+page.svelte create mode 100644 src/routes/(app)/results/ResultEntryModal.svelte diff --git a/COMPONENT_ORGANIZATION.md b/COMPONENT_ORGANIZATION.md deleted file mode 100644 index 1d79054..0000000 --- a/COMPONENT_ORGANIZATION.md +++ /dev/null @@ -1,155 +0,0 @@ -# Component Organization Guide - -Guide for splitting large components and modals into manageable files. - -## When to Split Components - -Split a component when: -- File exceeds 200 lines -- Component has multiple distinct sections (tabs, steps, panels) -- Logic becomes hard to follow -- Multiple developers work on different parts - -## Modal Organization Pattern - -### Structure for Large Modals - -``` -src/routes/(app)/feature/ -├── +page.svelte # Main page -├── FeatureModal.svelte # Main modal container -└── feature-modal/ # Modal sub-components (kebab-case folder) - ├── modals/ # Nested modals - │ └── PickerModal.svelte - └── tabs/ # Tab content components - ├── BasicInfoTab.svelte - ├── SettingsTab.svelte - └── AdvancedTab.svelte -``` - -### Example: Test Form Modal - -**Location**: `src/routes/(app)/master-data/tests/test-modal/` - -```svelte - - - - - {#snippet children()} -
- - - -
- - {#if activeTab === 'basic'} - - {:else if activeTab === 'technical'} - - {:else if activeTab === 'calculation'} - - {/if} - {/snippet} -
-``` - -```svelte - - - -
-
- - -
-
- - -
-
-``` - -## Data Flow - -### Parent to Child -- Pass data via props (`bind:formData`) -- Use `$bindable()` for two-way binding -- Keep state in parent when shared across tabs - -### Child to Parent -- Use callbacks for actions (`onSave`, `onClose`) -- Modify bound data directly (with `$bindable`) -- Emit events for complex interactions - -## Props Interface Pattern - -```javascript -// Define props with JSDoc -/** @type {{ formData: Object, onValidate: Function, readonly: boolean }} */ -let { - formData = $bindable({}), - onValidate = () => true, - readonly = false -} = $props(); -``` - -## Naming Conventions - -- **Main modal**: `{Feature}Modal.svelte` (e.g., `TestFormModal.svelte`) -- **Tab components**: `{TabName}Tab.svelte` (e.g., `BasicInfoTab.svelte`) -- **Nested modals**: `{Action}Modal.svelte` (e.g., `ConfirmDeleteModal.svelte`) -- **Folder names**: kebab-case matching the modal name (e.g., `test-modal/`) - -## Shared State Management - -For complex modals with shared state across tabs: - -```javascript -// In main modal -let sharedState = $state({ - dirty: false, - errors: {}, - selectedItems: [] -}); - -// Pass to tabs - -``` - -## Import Order in Sub-components - -Same as main components: -1. Svelte imports -2. `$lib/*` imports -3. External libraries -4. Relative imports (other tabs/modals) - -## Testing Split Components - -```bash -# Test individual tab component -vitest run src/routes/feature/modal-tabs/BasicInfoTab.test.js - -# Test main modal integration -vitest run src/routes/feature/FeatureModal.test.js -``` - -## Benefits - -- **Maintainability**: Each file has single responsibility -- **Collaboration**: Multiple developers can work on different tabs -- **Testing**: Test individual sections in isolation -- **Performance**: Only render visible tab content -- **Reusability**: Tabs can be used in different modals diff --git a/cookies.txt b/cookies.txt new file mode 100644 index 0000000..f63b530 --- /dev/null +++ b/cookies.txt @@ -0,0 +1,5 @@ +# Netscape HTTP Cookie File +# https://curl.se/docs/http-cookies.html +# This file was generated by libcurl! Edit at your own risk. + +#HttpOnly_localhost FALSE / FALSE 1773480246 token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyaWQiOiIxIiwicm9sZWlkIjoiMSIsInVzZXJuYW1lIjoibGlzZnNlIiwiZXhwIjoxNzczNDgwMjQ2fQ.EvHSR_Gp86vlK3swjVU8KNv2EjWgwnSUhkeZM3_4Rhs diff --git a/docs/api-docs.bundled.yaml b/docs/api-docs.bundled.yaml new file mode 100644 index 0000000..70a345a --- /dev/null +++ b/docs/api-docs.bundled.yaml @@ -0,0 +1,6451 @@ +openapi: 3.1.0 +info: + title: CLQMS - Clinical Laboratory Quality Management System API + description: | + API for Clinical Laboratory Quality Management System supporting patient management, + specimen tracking, test ordering, instrument integration, and laboratory operations. + + **IMPORTANT:** For OpenAPI tools (Swagger UI, Redoc, Postman, etc.), use the bundled file: + `api-docs.bundled.yaml` which contains all paths and schemas merged into one file. + + This file (api-docs.yaml) contains schema references and is meant for development. + The paths are defined in separate files in the `paths/` directory. + version: 1.0.0 + contact: + name: CLQMS API Support + license: + name: Proprietary +servers: + - url: http://localhost/clqms01/ + description: Local development server + - url: https://clqms01-api.services-summit.my.id/ + description: Production server +tags: + - name: Authentication + description: User authentication and session management + - name: Patients + description: Patient registration and management + - name: Patient Visits + description: Patient visit/encounter management + - name: Organization + description: Organization structure (accounts, sites, disciplines, departments, workstations) + - name: Specimen + description: Specimen and container management + - name: Tests + description: Test definitions and test catalog + - name: Orders + description: Laboratory order management + - name: Results + description: Patient results reporting with auto-validation + - name: Reports + description: Lab report generation (HTML view) + - name: Edge API + description: Instrument integration endpoints + - name: Contacts + description: Contact management (doctors, practitioners, etc.) + - name: Locations + description: Location management (rooms, wards, buildings) + - name: ValueSets + description: Value set definitions and items + - name: Demo + description: Demo/test endpoints (no authentication) + - name: EquipmentList + description: Laboratory equipment and instrument management +paths: + /api/auth/login: + post: + tags: + - Authentication + summary: User login + description: Authenticate user and receive JWT token via HTTP-only cookie + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LoginRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/LoginRequest' + responses: + '200': + description: Login successful + headers: + Set-Cookie: + description: JWT token in HTTP-only cookie + schema: + type: string + content: + application/json: + schema: + $ref: '#/components/schemas/LoginResponse' + '400': + description: Missing username + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: Invalid credentials + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /api/auth/logout: + post: + tags: + - Authentication + summary: User logout + description: Clear JWT token cookie + security: + - bearerAuth: [] + responses: + '200': + description: Logout successful + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + /api/auth/check: + get: + tags: + - Authentication + summary: Check authentication status + security: + - bearerAuth: [] + - cookieAuth: [] + responses: + '200': + description: Authenticated + content: + application/json: + schema: + type: object + properties: + authenticated: + type: boolean + user: + type: object + '401': + description: Not authenticated + /api/auth/register: + post: + tags: + - Authentication + summary: Register new user + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RegisterRequest' + responses: + '201': + description: User created + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + /api/auth/change_pass: + post: + tags: + - Authentication + summary: Change password + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - current_password + - new_password + properties: + current_password: + type: string + format: password + new_password: + type: string + format: password + responses: + '200': + description: Password changed successfully + /v2/auth/login: + post: + tags: + - Authentication + summary: V2 User login + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/LoginRequest' + responses: + '200': + description: Login successful + content: + application/json: + schema: + $ref: '#/components/schemas/LoginResponse' + /v2/auth/logout: + post: + tags: + - Authentication + summary: V2 User logout + responses: + '200': + description: Logout successful + /v2/auth/check: + get: + tags: + - Authentication + summary: V2 Check authentication + responses: + '200': + description: Auth check result + /v2/auth/register: + post: + tags: + - Authentication + summary: V2 Register new user + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RegisterRequest' + responses: + '201': + description: User created + /api/contact: + get: + tags: + - Contacts + summary: List contacts + security: + - bearerAuth: [] + parameters: + - name: ContactName + in: query + schema: + type: string + description: Filter by contact name (searches in NameFirst and NameLast) + - name: Specialty + in: query + schema: + type: string + description: Filter by medical specialty code + responses: + '200': + description: List of contacts + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '#/components/schemas/Contact' + post: + tags: + - Contacts + summary: Create new contact + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - NameFirst + properties: + NameFirst: + type: string + description: First name + NameLast: + type: string + description: Last name + Title: + type: string + description: Title (e.g., Dr, Mr, Mrs) + Initial: + type: string + description: Middle initial + Birthdate: + type: string + format: date-time + description: Date of birth + EmailAddress1: + type: string + format: email + description: Primary email address + EmailAddress2: + type: string + format: email + description: Secondary email address + Phone: + type: string + description: Primary phone number + MobilePhone1: + type: string + description: Primary mobile number + MobilePhone2: + type: string + description: Secondary mobile number + Specialty: + type: string + description: Medical specialty code + SubSpecialty: + type: string + description: Sub-specialty code + responses: + '201': + description: Contact created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + patch: + tags: + - Contacts + summary: Update contact + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - ContactID + - NameFirst + properties: + ContactID: + type: integer + description: Contact ID to update + NameFirst: + type: string + description: First name + NameLast: + type: string + description: Last name + Title: + type: string + description: Title (e.g., Dr, Mr, Mrs) + Initial: + type: string + description: Middle initial + Birthdate: + type: string + format: date-time + description: Date of birth + EmailAddress1: + type: string + format: email + description: Primary email address + EmailAddress2: + type: string + format: email + description: Secondary email address + Phone: + type: string + description: Primary phone number + MobilePhone1: + type: string + description: Primary mobile number + MobilePhone2: + type: string + description: Secondary mobile number + Specialty: + type: string + description: Medical specialty code + SubSpecialty: + type: string + description: Sub-specialty code + responses: + '201': + description: Contact updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + delete: + tags: + - Contacts + summary: Delete contact + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - ContactID + properties: + ContactID: + type: integer + description: Contact ID to delete + responses: + '200': + description: Contact deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + /api/contact/{id}: + get: + tags: + - Contacts + summary: Get contact by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: Contact ID + responses: + '200': + description: Contact details + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/Contact' + /api/demo/hello: + get: + tags: + - Demo + summary: Hello world endpoint + description: Simple test endpoint that returns a greeting message + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + example: Hello, World! + /api/demo/ping: + get: + tags: + - Demo + summary: Ping endpoint + description: Health check endpoint to verify API is running + responses: + '200': + description: API is running + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + example: pong + timestamp: + type: string + format: date-time + /api/edge/results: + post: + tags: + - Edge API + summary: Receive results from instrument (tiny-edge) + description: | + Receives instrument results and stores them in the edgeres table for processing. + This endpoint is typically called by the tiny-edge middleware connected to laboratory analyzers. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/EdgeResultRequest' + responses: + '201': + description: Result received and queued + content: + application/json: + schema: + $ref: '#/components/schemas/EdgeResultResponse' + '400': + description: Invalid JSON payload + /api/edge/orders: + get: + tags: + - Edge API + summary: Fetch pending orders for instruments + description: Returns orders that need to be sent to laboratory instruments for testing + parameters: + - name: instrument_id + in: query + schema: + type: string + description: Filter by instrument + - name: status + in: query + schema: + type: string + enum: + - pending + - acknowledged + description: Filter by status + responses: + '200': + description: List of orders + content: + application/json: + schema: + type: object + properties: + status: + type: string + data: + type: array + items: + $ref: '#/components/schemas/EdgeOrder' + /api/edge/orders/{orderId}/ack: + post: + tags: + - Edge API + summary: Acknowledge order delivery + description: Mark order as acknowledged by the instrument + parameters: + - name: orderId + in: path + required: true + schema: + type: integer + description: Edge order ID + responses: + '200': + description: Order acknowledged + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + /api/edge/status: + post: + tags: + - Edge API + summary: Log instrument status update + description: Receive status updates from laboratory instruments + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - instrument_id + - status + properties: + instrument_id: + type: string + status: + type: string + enum: + - online + - offline + - error + - maintenance + message: + type: string + timestamp: + type: string + format: date-time + responses: + '200': + description: Status logged + /api/equipmentlist: + get: + tags: + - EquipmentList + summary: List equipment + description: Get list of equipment with optional filters + security: + - bearerAuth: [] + parameters: + - name: IEID + in: query + schema: + type: string + description: Filter by IEID + - name: InstrumentName + in: query + schema: + type: string + description: Filter by instrument name + - name: DepartmentID + in: query + schema: + type: integer + description: Filter by department ID + - name: WorkstationID + in: query + schema: + type: integer + description: Filter by workstation ID + - name: Enable + in: query + schema: + type: integer + enum: + - 0 + - 1 + description: Filter by enable status + responses: + '200': + description: List of equipment + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '#/components/schemas/EquipmentList' + post: + tags: + - EquipmentList + summary: Create equipment + description: Create a new equipment entry + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - IEID + - DepartmentID + - Enable + - EquipmentRole + properties: + IEID: + type: string + maxLength: 50 + DepartmentID: + type: integer + InstrumentID: + type: string + maxLength: 150 + InstrumentName: + type: string + maxLength: 150 + WorkstationID: + type: integer + Enable: + type: integer + enum: + - 0 + - 1 + EquipmentRole: + type: string + maxLength: 1 + responses: + '201': + description: Equipment created + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: integer + patch: + tags: + - EquipmentList + summary: Update equipment + description: Update an existing equipment entry + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - EID + properties: + EID: + type: integer + IEID: + type: string + maxLength: 50 + DepartmentID: + type: integer + InstrumentID: + type: string + maxLength: 150 + InstrumentName: + type: string + maxLength: 150 + WorkstationID: + type: integer + Enable: + type: integer + enum: + - 0 + - 1 + EquipmentRole: + type: string + maxLength: 1 + responses: + '200': + description: Equipment updated + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: integer + delete: + tags: + - EquipmentList + summary: Delete equipment + description: Soft delete an equipment entry + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - EID + properties: + EID: + type: integer + responses: + '200': + description: Equipment deleted + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + /api/equipmentlist/{id}: + get: + tags: + - EquipmentList + summary: Get equipment by ID + description: Get a single equipment entry by its EID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: Equipment ID + responses: + '200': + description: Equipment details + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/EquipmentList' + /api/location: + get: + tags: + - Locations + summary: List locations + security: + - bearerAuth: [] + parameters: + - name: LocCode + in: query + schema: + type: string + description: Filter by location code + - name: LocName + in: query + schema: + type: string + description: Filter by location name (searches in LocFull) + responses: + '200': + description: List of locations + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '#/components/schemas/Location' + post: + tags: + - Locations + summary: Create location + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - LocCode + - LocFull + properties: + SiteID: + type: integer + description: Reference to site + LocCode: + type: string + maxLength: 6 + description: Location code (short identifier) + Parent: + type: integer + nullable: true + description: Parent location ID for hierarchical locations + LocFull: + type: string + maxLength: 255 + description: Full location name + Description: + type: string + maxLength: 255 + description: Location description + LocType: + type: string + description: Location type code (e.g., ROOM, WARD, BUILDING) + responses: + '201': + description: Location created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + patch: + tags: + - Locations + summary: Update location + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - LocationID + properties: + LocationID: + type: integer + description: Location ID to update + SiteID: + type: integer + description: Reference to site + LocCode: + type: string + maxLength: 6 + description: Location code (short identifier) + Parent: + type: integer + nullable: true + description: Parent location ID for hierarchical locations + LocFull: + type: string + maxLength: 255 + description: Full location name + Description: + type: string + maxLength: 255 + description: Location description + LocType: + type: string + description: Location type code (e.g., ROOM, WARD, BUILDING) + responses: + '201': + description: Location updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + delete: + tags: + - Locations + summary: Delete location + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - LocationID + properties: + LocationID: + type: integer + description: Location ID to delete + responses: + '200': + description: Location deleted successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + /api/location/{id}: + get: + tags: + - Locations + summary: Get location by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: Location ID + responses: + '200': + description: Location details + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/Location' + /api/ordertest: + get: + tags: + - Orders + summary: List orders + security: + - bearerAuth: [] + parameters: + - name: page + in: query + schema: + type: integer + - name: perPage + in: query + schema: + type: integer + - name: InternalPID + in: query + schema: + type: integer + description: Filter by internal patient ID + - name: OrderStatus + in: query + schema: + type: string + enum: + - ORD + - SCH + - ANA + - VER + - REV + - REP + description: | + ORD: Ordered + SCH: Scheduled + ANA: Analysis + VER: Verified + REV: Reviewed + REP: Reported + - name: include + in: query + schema: + type: string + enum: + - details + description: Include specimens and tests in response + 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/OrderTest' + post: + tags: + - Orders + 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 + patch: + tags: + - Orders + summary: Update order + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - OrderID + properties: + OrderID: + type: string + 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' + delete: + tags: + - Orders + 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: + - Orders + summary: Update order status + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - OrderID + - OrderStatus + properties: + OrderID: + type: string + OrderStatus: + type: string + enum: + - ORD + - SCH + - ANA + - VER + - REV + - REP + description: | + ORD: Ordered + SCH: Scheduled + ANA: Analysis + VER: Verified + REV: Reviewed + REP: Reported + responses: + '200': + description: Order status updated + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/OrderTest' + /api/ordertest/{id}: + get: + tags: + - Orders + 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' + /api/organization/account/{id}: + get: + tags: + - Organization + summary: Get account by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Account details + content: + application/json: + schema: + $ref: '#/components/schemas/Account' + /api/organization/site: + get: + tags: + - Organization + summary: List sites + security: + - bearerAuth: [] + responses: + '200': + description: List of sites + post: + tags: + - Organization + summary: Create site + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Site' + responses: + '201': + description: Site created + patch: + tags: + - Organization + summary: Update site + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - id + properties: + id: + type: integer + SiteName: + type: string + SiteCode: + type: string + AccountID: + type: integer + responses: + '200': + description: Site updated + delete: + tags: + - Organization + summary: Delete site + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - id + properties: + id: + type: integer + responses: + '200': + description: Site deleted + /api/organization/site/{id}: + get: + tags: + - Organization + summary: Get site by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Site details + /api/organization/discipline: + get: + tags: + - Organization + summary: List disciplines + security: + - bearerAuth: [] + responses: + '200': + description: List of disciplines + post: + tags: + - Organization + summary: Create discipline + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Discipline' + responses: + '201': + description: Discipline created + patch: + tags: + - Organization + summary: Update discipline + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - id + properties: + id: + type: integer + DisciplineName: + type: string + DisciplineCode: + type: string + responses: + '200': + description: Discipline updated + delete: + tags: + - Organization + summary: Delete discipline + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - id + properties: + id: + type: integer + responses: + '200': + description: Discipline deleted + /api/organization/discipline/{id}: + get: + tags: + - Organization + summary: Get discipline by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Discipline details + /api/organization/department: + get: + tags: + - Organization + summary: List departments + security: + - bearerAuth: [] + responses: + '200': + description: List of departments + post: + tags: + - Organization + summary: Create department + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Department' + responses: + '201': + description: Department created + patch: + tags: + - Organization + summary: Update department + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - id + properties: + id: + type: integer + DeptName: + type: string + DeptCode: + type: string + SiteID: + type: integer + responses: + '200': + description: Department updated + delete: + tags: + - Organization + summary: Delete department + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - id + properties: + id: + type: integer + responses: + '200': + description: Department deleted + /api/organization/department/{id}: + get: + tags: + - Organization + summary: Get department by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Department details + /api/organization/workstation: + get: + tags: + - Organization + summary: List workstations + security: + - bearerAuth: [] + responses: + '200': + description: List of workstations + post: + tags: + - Organization + summary: Create workstation + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Workstation' + responses: + '201': + description: Workstation created + patch: + tags: + - Organization + summary: Update workstation + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - id + properties: + id: + type: integer + WorkstationName: + type: string + WorkstationCode: + type: string + SiteID: + type: integer + DepartmentID: + type: integer + responses: + '200': + description: Workstation updated + delete: + tags: + - Organization + summary: Delete workstation + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - id + properties: + id: + type: integer + responses: + '200': + description: Workstation deleted + /api/organization/workstation/{id}: + get: + tags: + - Organization + summary: Get workstation by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Workstation details + /api/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 + patch: + tags: + - Organization + summary: Update host application + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - HostAppID + properties: + HostAppID: + type: string + HostAppName: + type: string + SiteID: + type: integer + responses: + '200': + description: Host application updated + 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' + /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 + patch: + tags: + - Organization + summary: Update host communication parameters + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - HostAppID + properties: + HostAppID: + type: string + HostIP: + type: string + HostPort: + type: string + HostPwd: + type: string + responses: + '200': + description: Host communication parameters updated + 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' + /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 + patch: + tags: + - Organization + summary: Update coding system + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - CodingSysID + properties: + CodingSysID: + type: integer + CodingSysAbb: + type: string + FullText: + type: string + Description: + type: string + responses: + '200': + description: Coding system updated + 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' + /api/patvisit: + get: + tags: + - Patient Visits + 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 Visits + summary: Create patient visit + description: | + Creates a new patient visit. PVID is auto-generated with 'DV' prefix if not provided. + Can optionally include PatDiag (diagnosis) and PatVisitADT (ADT information). + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - InternalPID + properties: + PVID: + type: string + description: Visit ID (auto-generated with DV prefix if not provided) + InternalPID: + type: integer + description: Patient ID (required) + EpisodeID: + type: string + description: Episode identifier + SiteID: + type: integer + description: Site reference + PatDiag: + type: object + description: Optional diagnosis information + properties: + DiagCode: + type: string + Diagnosis: + type: string + PatVisitADT: + type: object + description: Optional ADT information + properties: + ADTCode: + type: string + enum: + - A01 + - A02 + - A03 + - A04 + - A08 + LocationID: + type: integer + AttDoc: + type: integer + RefDoc: + type: integer + AdmDoc: + type: integer + CnsDoc: + type: integer + responses: + '201': + description: Visit created successfully + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: object + properties: + PVID: + type: string + InternalPVID: + type: integer + patch: + tags: + - Patient Visits + summary: Update patient visit + description: | + Updates an existing patient visit. InternalPVID is required. + Can update main visit data, PatDiag, and add new PatVisitADT records. + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - InternalPVID + properties: + InternalPVID: + type: integer + description: Visit ID (required) + PVID: + type: string + InternalPID: + type: integer + EpisodeID: + type: string + SiteID: + type: integer + PatDiag: + type: object + description: Diagnosis information (will update if exists) + properties: + DiagCode: + type: string + Diagnosis: + type: string + PatVisitADT: + type: array + description: Array of ADT records to add (new records only) + items: + type: object + properties: + ADTCode: + type: string + enum: + - A01 + - A02 + - A03 + - A04 + - A08 + LocationID: + type: integer + AttDoc: + type: integer + RefDoc: + type: integer + AdmDoc: + type: integer + CnsDoc: + type: integer + sequence: + type: integer + description: Used for ordering multiple ADT records + responses: + '200': + description: Visit updated successfully + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: object + properties: + PVID: + type: string + InternalPVID: + type: integer + delete: + tags: + - Patient Visits + summary: Delete patient visit + security: + - bearerAuth: [] + responses: + '200': + description: Visit deleted successfully + /api/patvisit/{id}: + get: + tags: + - Patient Visits + summary: Get visit by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: string + description: PVID (visit identifier like DV00001) + responses: + '200': + description: Visit details + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/PatientVisit' + /api/patvisit/patient/{patientId}: + get: + tags: + - Patient Visits + summary: Get visits by patient ID + security: + - bearerAuth: [] + parameters: + - name: patientId + in: path + required: true + schema: + type: integer + description: Internal Patient ID (InternalPID) + responses: + '200': + description: Patient visits list + content: + application/json: + schema: + type: object + properties: + status: + type: string + data: + type: array + items: + $ref: '#/components/schemas/PatientVisit' + /api/patvisitadt: + post: + tags: + - Patient Visits + summary: Create ADT record + description: Create a new Admission/Discharge/Transfer record + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PatVisitADT' + responses: + '201': + description: ADT record created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + patch: + tags: + - Patient Visits + summary: Update ADT record + description: Update an existing ADT record + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PatVisitADT' + responses: + '200': + description: ADT record updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + delete: + tags: + - Patient Visits + summary: Delete ADT visit (soft delete) + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - PVADTID + properties: + PVADTID: + type: integer + description: ADT record ID to delete + responses: + '200': + description: ADT visit deleted successfully + /api/patvisitadt/visit/{visitId}: + get: + tags: + - Patient Visits + summary: Get ADT history by visit ID + description: Retrieve the complete Admission/Discharge/Transfer history for a visit, including all locations and doctors + security: + - bearerAuth: [] + parameters: + - name: visitId + in: path + required: true + schema: + type: integer + description: Internal Visit ID (InternalPVID) + responses: + '200': + description: ADT history retrieved successfully + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + example: ADT history retrieved + data: + type: array + items: + type: object + properties: + PVADTID: + type: integer + InternalPVID: + type: integer + ADTCode: + type: string + enum: + - A01 + - A02 + - A03 + - A04 + - A08 + LocationID: + type: integer + LocationName: + type: string + AttDoc: + type: integer + AttDocFirstName: + type: string + AttDocLastName: + type: string + RefDoc: + type: integer + RefDocFirstName: + type: string + RefDocLastName: + type: string + AdmDoc: + type: integer + AdmDocFirstName: + type: string + AdmDocLastName: + type: string + CnsDoc: + type: integer + CnsDocFirstName: + type: string + CnsDocLastName: + type: string + CreateDate: + type: string + format: date-time + EndDate: + type: string + format: date-time + delete: + tags: + - Patient Visits + summary: Delete ADT visit (soft delete) + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - PVADTID + properties: + PVADTID: + type: integer + description: ADT record ID to delete + responses: + '200': + description: ADT visit deleted successfully + /api/patvisitadt/{id}: + get: + tags: + - Patient Visits + summary: Get ADT record by ID + description: Retrieve a single ADT record by its ID, including location and doctor details + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: ADT record ID (PVADTID) + responses: + '200': + description: ADT record retrieved successfully + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + example: ADT record retrieved + data: + type: object + properties: + PVADTID: + type: integer + InternalPVID: + type: integer + ADTCode: + type: string + enum: + - A01 + - A02 + - A03 + - A04 + - A08 + LocationID: + type: integer + LocationName: + type: string + AttDoc: + type: integer + AttDocFirstName: + type: string + AttDocLastName: + type: string + RefDoc: + type: integer + RefDocFirstName: + type: string + RefDocLastName: + type: string + AdmDoc: + type: integer + AdmDocFirstName: + type: string + AdmDocLastName: + type: string + CnsDoc: + type: integer + CnsDocFirstName: + type: string + CnsDocLastName: + type: string + CreateDate: + type: string + format: date-time + EndDate: + type: string + format: date-time + /api/patient: + get: + tags: + - Patients + summary: List patients + security: + - bearerAuth: [] + parameters: + - name: page + in: query + schema: + type: integer + default: 1 + - name: perPage + in: query + schema: + type: integer + default: 20 + - name: InternalPID + in: query + schema: + type: integer + description: Filter by internal patient ID + - name: PatientID + in: query + schema: + type: string + description: Filter by patient ID + - name: Name + in: query + schema: + type: string + description: Search by patient name + - name: Birthdate + in: query + schema: + type: string + format: date + description: Filter by birthdate (YYYY-MM-DD) + responses: + '200': + description: List of patients + content: + application/json: + schema: + $ref: '#/components/schemas/PatientListResponse' + post: + tags: + - Patients + summary: Create new patient + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Patient' + responses: + '201': + description: Patient created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + '422': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + patch: + tags: + - Patients + summary: Update patient + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Patient' + responses: + '200': + description: Patient updated successfully + delete: + tags: + - Patients + summary: Delete patient (soft delete) + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - InternalPID + properties: + InternalPID: + type: integer + description: Internal patient record ID + responses: + '200': + description: Patient deleted successfully + /api/patient/check: + get: + tags: + - Patients + summary: Check if patient exists + security: + - bearerAuth: [] + parameters: + - name: PatientID + in: query + schema: + type: string + description: Patient ID to check + - name: EmailAddress1 + in: query + schema: + type: string + format: email + description: Email address to check + responses: + '200': + description: Patient check result + content: + application/json: + schema: + type: object + properties: + exists: + type: boolean + data: + $ref: '#/components/schemas/Patient' + /api/patient/{id}: + get: + tags: + - Patients + summary: Get patient by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: Internal patient record ID + responses: + '200': + description: Patient details + content: + application/json: + schema: + type: object + properties: + status: + type: string + data: + $ref: '#/components/schemas/Patient' + /api/reports/{orderID}: + get: + tags: + - Reports + 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/results: + get: + tags: + - Results + 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/results/{id}: + get: + tags: + - Results + 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: + - Results + 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: + - Results + 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/specimen: + get: + tags: + - Specimen + summary: List specimens + security: + - bearerAuth: [] + responses: + '200': + description: List of specimens + post: + tags: + - Specimen + summary: Create specimen + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Specimen' + responses: + '201': + description: Specimen created + patch: + tags: + - Specimen + summary: Update specimen + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Specimen' + responses: + '200': + description: Specimen updated + /api/specimen/{id}: + get: + tags: + - Specimen + summary: Get specimen by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Specimen details + /api/specimen/container: + get: + tags: + - Specimen + summary: List container definitions + security: + - bearerAuth: [] + responses: + '200': + description: List of container definitions + post: + tags: + - Specimen + summary: Create container definition + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ContainerDef' + responses: + '201': + description: Container definition created + patch: + tags: + - Specimen + summary: Update container definition + security: + - bearerAuth: [] + responses: + '200': + description: Container definition updated + /api/specimen/container/{id}: + get: + tags: + - Specimen + summary: Get container definition by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Container definition details + /api/specimen/containerdef: + get: + tags: + - Specimen + summary: List container definitions (alias) + security: + - bearerAuth: [] + responses: + '200': + description: List of container definitions + post: + tags: + - Specimen + summary: Create container definition (alias) + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ContainerDef' + responses: + '201': + description: Container definition created + patch: + tags: + - Specimen + summary: Update container definition (alias) + security: + - bearerAuth: [] + responses: + '200': + description: Container definition updated + /api/specimen/prep: + get: + tags: + - Specimen + summary: List specimen preparations + security: + - bearerAuth: [] + responses: + '200': + description: List of specimen preparations + post: + tags: + - Specimen + summary: Create specimen preparation + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SpecimenPrep' + responses: + '201': + description: Specimen preparation created + patch: + tags: + - Specimen + summary: Update specimen preparation + security: + - bearerAuth: [] + responses: + '200': + description: Specimen preparation updated + /api/specimen/prep/{id}: + get: + tags: + - Specimen + summary: Get specimen preparation by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Specimen preparation details + /api/specimen/status: + get: + tags: + - Specimen + summary: List specimen statuses + security: + - bearerAuth: [] + responses: + '200': + description: List of specimen statuses + post: + tags: + - Specimen + summary: Create specimen status + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SpecimenStatus' + responses: + '201': + description: Specimen status created + patch: + tags: + - Specimen + summary: Update specimen status + security: + - bearerAuth: [] + responses: + '200': + description: Specimen status updated + /api/specimen/status/{id}: + get: + tags: + - Specimen + summary: Get specimen status by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Specimen status details + /api/specimen/collection: + get: + tags: + - Specimen + summary: List specimen collection methods + security: + - bearerAuth: [] + responses: + '200': + description: List of collection methods + post: + tags: + - Specimen + summary: Create specimen collection method + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SpecimenCollection' + responses: + '201': + description: Collection method created + patch: + tags: + - Specimen + summary: Update specimen collection method + security: + - bearerAuth: [] + responses: + '200': + description: Collection method updated + /api/specimen/collection/{id}: + get: + tags: + - Specimen + summary: Get specimen collection method by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: Collection method details + /api/test/testmap: + get: + tags: + - Tests + summary: List all test mappings + security: + - bearerAuth: [] + 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: + - Tests + 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 + patch: + tags: + - Tests + summary: Update test mapping + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestMapID: + type: integer + description: Test Map ID (required) + TestCode: + type: string + description: Test Code - maps to HostTestCode or ClientTestCode + HostType: + type: string + HostID: + type: string + ClientType: + type: string + ClientID: + type: string + required: + - TestMapID + responses: + '200': + description: Test mapping updated + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: integer + description: Updated TestMapID + delete: + tags: + - Tests + summary: Soft delete test mapping (cascades to details) + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestMapID: + type: integer + description: Test Map ID to delete (required) + required: + - TestMapID + responses: + '200': + description: Test mapping deleted successfully + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: integer + description: Deleted TestMapID + '404': + description: Test mapping not found or already deleted + /api/test/testmap/{id}: + get: + tags: + - Tests + summary: Get test mapping by ID with details + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: Test Map ID + responses: + '200': + description: Test mapping details with nested detail records + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/TestMap' + '404': + description: Test mapping not found + /api/test/testmap/by-testcode/{testCode}: + get: + tags: + - Tests + 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: + - Tests + summary: List test mapping details + security: + - bearerAuth: [] + parameters: + - name: TestMapID + in: query + schema: + type: integer + description: Filter by TestMapID + responses: + '200': + description: List of test mapping details + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '#/components/schemas/TestMapDetail' + post: + tags: + - Tests + summary: Create test mapping detail + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestMapID: + type: integer + description: Test Map ID (required) + HostTestCode: + type: string + HostTestName: + type: string + ConDefID: + type: integer + ClientTestCode: + type: string + ClientTestName: + type: string + required: + - TestMapID + responses: + '201': + description: Test mapping detail created + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: integer + description: Created TestMapDetailID + patch: + tags: + - Tests + summary: Update test mapping detail + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestMapDetailID: + type: integer + description: Test Map Detail ID (required) + TestMapID: + type: integer + HostTestCode: + type: string + HostTestName: + type: string + ConDefID: + type: integer + ClientTestCode: + type: string + ClientTestName: + type: string + required: + - TestMapDetailID + responses: + '200': + description: Test mapping detail updated + delete: + tags: + - Tests + summary: Soft delete test mapping detail + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestMapDetailID: + type: integer + description: Test Map Detail ID to delete (required) + required: + - TestMapDetailID + responses: + '200': + description: Test mapping detail deleted + /api/test/testmap/detail/{id}: + get: + tags: + - Tests + summary: Get test mapping detail by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: Test Map Detail ID + responses: + '200': + description: Test mapping detail + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/TestMapDetail' + /api/test/testmap/detail/by-testmap/{testMapID}: + get: + tags: + - Tests + summary: Get test mapping details by test map ID + security: + - bearerAuth: [] + parameters: + - name: testMapID + in: path + required: true + schema: + type: integer + description: Test Map ID + responses: + '200': + description: List of test mapping details + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + type: array + items: + $ref: '#/components/schemas/TestMapDetail' + /api/test/testmap/detail/batch: + post: + tags: + - Tests + summary: Batch create test mapping details + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + properties: + TestMapID: + type: integer + HostTestCode: + type: string + HostTestName: + type: string + ConDefID: + type: integer + ClientTestCode: + type: string + ClientTestName: + type: string + responses: + '200': + description: Batch create results + patch: + tags: + - Tests + summary: Batch update test mapping details + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: object + properties: + TestMapDetailID: + type: integer + TestMapID: + type: integer + HostTestCode: + type: string + HostTestName: + type: string + ConDefID: + type: integer + ClientTestCode: + type: string + ClientTestName: + type: string + responses: + '200': + description: Batch update results + delete: + tags: + - Tests + summary: Batch delete test mapping details + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: integer + description: TestMapDetailIDs to delete + responses: + '200': + description: Batch delete results + /api/tests: + get: + tags: + - Tests + summary: List test definitions + security: + - bearerAuth: [] + parameters: + - name: page + in: query + schema: + type: integer + default: 1 + description: Page number for pagination + - name: perPage + in: query + schema: + type: integer + default: 20 + description: Number of items per page + - name: SiteID + in: query + schema: + type: integer + description: Filter by site ID + - name: TestType + in: query + schema: + type: string + enum: + - TEST + - PARAM + - CALC + - GROUP + - TITLE + description: Filter by test type + - name: VisibleScr + in: query + schema: + type: integer + enum: + - 0 + - 1 + description: Filter by screen visibility (0=hidden, 1=visible) + - name: VisibleRpt + in: query + schema: + type: integer + enum: + - 0 + - 1 + description: Filter by report visibility (0=hidden, 1=visible) + - name: search + in: query + schema: + type: string + description: Search by test code or name + responses: + '200': + description: List of test definitions + content: + application/json: + schema: + type: object + properties: + status: + type: string + data: + type: array + items: + $ref: '#/components/schemas/TestDefinition' + pagination: + type: object + properties: + total: + type: integer + description: Total number of records matching the query + post: + tags: + - Tests + summary: Create test definition + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + SiteID: + type: integer + description: Site ID (required) + TestSiteCode: + type: string + description: Test code (required) + TestSiteName: + type: string + description: Test name (required) + TestType: + type: string + enum: + - TEST + - PARAM + - CALC + - GROUP + - TITLE + description: Test type (required) + Description: + type: string + DisciplineID: + type: integer + DepartmentID: + type: integer + ResultType: + type: string + enum: + - NMRIC + - RANGE + - TEXT + - VSET + - NORES + RefType: + type: string + enum: + - RANGE + - THOLD + - VSET + - TEXT + - NOREF + VSet: + type: integer + ReqQty: + type: number + format: decimal + ReqQtyUnit: + type: string + Unit1: + type: string + Factor: + type: number + format: decimal + Unit2: + type: string + Decimal: + type: integer + CollReq: + type: string + Method: + type: string + ExpectedTAT: + type: integer + SeqScr: + type: integer + SeqRpt: + type: integer + IndentLeft: + type: integer + FontStyle: + type: string + VisibleScr: + type: integer + VisibleRpt: + type: integer + CountStat: + type: integer + details: + type: object + description: Type-specific details + refnum: + type: array + items: + type: object + reftxt: + type: array + items: + type: object + testmap: + type: array + items: + type: object + required: + - SiteID + - TestSiteCode + - TestSiteName + - TestType + responses: + '201': + description: Test definition created + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: created + message: + type: string + data: + type: object + properties: + TestSiteId: + type: integer + patch: + tags: + - Tests + summary: Update test definition + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + TestSiteID: + type: integer + description: Test Site ID (required) + TestSiteCode: + type: string + TestSiteName: + type: string + TestType: + type: string + enum: + - TEST + - PARAM + - CALC + - GROUP + - TITLE + Description: + type: string + DisciplineID: + type: integer + DepartmentID: + type: integer + ResultType: + type: string + enum: + - NMRIC + - RANGE + - TEXT + - VSET + - NORES + RefType: + type: string + enum: + - RANGE + - THOLD + - VSET + - TEXT + - NOREF + VSet: + type: integer + ReqQty: + type: number + format: decimal + ReqQtyUnit: + type: string + Unit1: + type: string + Factor: + type: number + format: decimal + Unit2: + type: string + Decimal: + type: integer + CollReq: + type: string + Method: + type: string + ExpectedTAT: + type: integer + SeqScr: + type: integer + SeqRpt: + type: integer + IndentLeft: + type: integer + FontStyle: + type: string + VisibleScr: + type: integer + VisibleRpt: + type: integer + CountStat: + type: integer + details: + type: object + description: Type-specific details + refnum: + type: array + items: + type: object + reftxt: + type: array + items: + type: object + testmap: + type: array + items: + type: object + required: + - TestSiteID + responses: + '200': + description: Test definition updated + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: object + properties: + TestSiteId: + type: integer + /api/tests/{id}: + get: + tags: + - Tests + summary: Get test definition by ID + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: Test Site ID + responses: + '200': + description: Test definition details + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/TestDefinition' + '404': + description: Test not found + delete: + tags: + - Tests + summary: Soft delete test definition + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + description: Test Site ID to delete + requestBody: + content: + application/json: + schema: + type: object + properties: + TestSiteID: + type: integer + description: Optional - can be provided in body instead of path + responses: + '200': + description: Test disabled successfully + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + data: + type: object + properties: + TestSiteId: + type: integer + EndDate: + type: string + format: date-time + '404': + description: Test not found + '422': + description: Test already disabled + /api/valueset: + get: + tags: + - ValueSets + summary: List lib value sets + description: List all library/system value sets from JSON files with item counts. Returns an array of objects with value, label, and count properties. + security: + - bearerAuth: [] + parameters: + - name: search + in: query + schema: + type: string + description: Optional search term to filter value set names or labels + responses: + '200': + description: List of lib value sets with item counts + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + data: + type: array + items: + $ref: '#/components/schemas/ValueSetListItem' + example: + - value: sex + label: Sex + count: 3 + - value: marital_status + label: Marital Status + count: 6 + - value: order_status + label: Order Status + count: 6 + /api/valueset/{key}: + get: + tags: + - ValueSets + summary: Get lib value set by key + description: | + Get a specific library/system value set from JSON files. + + **Available value set keys:** + - `activity_result` - Activity Result + - `additive` - Additive + - `adt_event` - ADT Event + - `area_class` - Area Class + - `body_site` - Body Site + - `collection_method` - Collection Method + - `container_cap_color` - Container Cap Color + - `container_class` - Container Class + - `container_size` - Container Size + - `country` - Country + - `death_indicator` - Death Indicator + - `did_type` - DID Type + - `enable_disable` - Enable/Disable + - `entity_type` - Entity Type + - `ethnic` - Ethnic + - `fasting_status` - Fasting Status + - `formula_language` - Formula Language + - `generate_by` - Generate By + - `identifier_type` - Identifier Type + - `location_type` - Location Type + - `marital_status` - Marital Status + - `math_sign` - Math Sign + - `numeric_ref_type` - Numeric Reference Type + - `operation` - Operation (CRUD) + - `order_priority` - Order Priority + - `order_status` - Order Status + - `race` - Race (Ethnicity) + - `range_type` - Range Type + - `reference_type` - Reference Type + - `religion` - Religion + - `requested_entity` - Requested Entity + - `result_type` - Result Type + - `result_unit` - Result Unit + - `sex` - Sex + - `site_class` - Site Class + - `site_type` - Site Type + - `specimen_activity` - Specimen Activity + - `specimen_condition` - Specimen Condition + - `specimen_role` - Specimen Role + - `specimen_status` - Specimen Status + - `specimen_type` - Specimen Type + - `test_activity` - Test Activity + - `test_type` - Test Type + - `text_ref_type` - Text Reference Type + - `unit` - Unit + - `v_category` - VCategory + - `ws_type` - Workstation Type + security: + - bearerAuth: [] + parameters: + - name: key + in: path + required: true + schema: + type: string + enum: + - activity_result + - additive + - adt_event + - area_class + - body_site + - collection_method + - container_cap_color + - container_class + - container_size + - country + - death_indicator + - did_type + - enable_disable + - entity_type + - ethnic + - fasting_status + - formula_language + - generate_by + - identifier_type + - location_type + - marital_status + - math_sign + - numeric_ref_type + - operation + - order_priority + - order_status + - race + - range_type + - reference_type + - religion + - requested_entity + - result_type + - result_unit + - sex + - site_class + - site_type + - specimen_activity + - specimen_condition + - specimen_role + - specimen_status + - specimen_type + - test_activity + - test_type + - text_ref_type + - unit + - v_category + - ws_type + description: Value set key name + responses: + '200': + description: Lib value set details + content: + application/json: + schema: + type: object + properties: + status: + type: string + data: + type: array + items: + $ref: '#/components/schemas/ValueSetLibItem' + /api/valueset/refresh: + post: + tags: + - ValueSets + summary: Refresh lib ValueSet cache + description: Clear and reload the library/system ValueSet cache from JSON files. Call this after modifying JSON files in app/Libraries/Data/. + security: + - bearerAuth: [] + responses: + '200': + description: Lib ValueSet cache refreshed + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: success + message: + type: string + example: Cache cleared + /api/valueset/user/items: + get: + tags: + - ValueSets + summary: List user value set items + description: List value set items from database (user-defined) + security: + - bearerAuth: [] + parameters: + - name: VSetID + in: query + schema: + type: integer + description: Filter by ValueSet ID + - name: search + in: query + schema: + type: string + description: Search term to filter by VValue, VDesc, or VSName + - name: param + in: query + schema: + type: string + description: Alternative search parameter (alias for search) + responses: + '200': + description: List of user value set items + content: + application/json: + schema: + type: object + properties: + status: + type: string + data: + type: array + items: + $ref: '#/components/schemas/ValueSetItem' + post: + tags: + - ValueSets + summary: Create user value set item + description: Create value set item in database (user-defined) + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - VSetID + properties: + SiteID: + type: integer + description: Site reference (default 1) + VSetID: + type: integer + description: Reference to value set definition (required) + VOrder: + type: integer + description: Display order (default 0) + VValue: + type: string + description: The value code + VDesc: + type: string + description: The display description/label + responses: + '201': + description: User value set item created + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/ValueSetItem' + /api/valueset/user/items/{id}: + get: + tags: + - ValueSets + summary: Get user value set item by ID + description: Get value set item from database (user-defined) + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: User value set item details + content: + application/json: + schema: + type: object + properties: + status: + type: string + data: + $ref: '#/components/schemas/ValueSetItem' + put: + tags: + - ValueSets + summary: Update user value set item + description: Update value set item in database (user-defined) + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + SiteID: + type: integer + description: Site reference + VSetID: + type: integer + description: Reference to value set definition + VOrder: + type: integer + description: Display order + VValue: + type: string + description: The value code + VDesc: + type: string + description: The display description/label + responses: + '200': + description: User value set item updated + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/ValueSetItem' + delete: + tags: + - ValueSets + summary: Delete user value set item + description: Delete value set item from database (user-defined) + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: User value set item deleted + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + /api/valueset/user/def: + get: + tags: + - ValueSets + summary: List user value set definitions + description: List value set definitions from database (user-defined) + security: + - bearerAuth: [] + parameters: + - name: search + in: query + schema: + type: string + description: Optional search term to filter definitions + - name: page + in: query + schema: + type: integer + default: 1 + description: Page number for pagination + - name: limit + in: query + schema: + type: integer + default: 100 + description: Number of items per page + responses: + '200': + description: List of user value set definitions + content: + application/json: + schema: + type: object + properties: + status: + type: string + data: + type: array + items: + $ref: '#/components/schemas/ValueSetDef' + meta: + type: object + properties: + total: + type: integer + page: + type: integer + limit: + type: integer + post: + tags: + - ValueSets + summary: Create user value set definition + description: Create value set definition in database (user-defined) + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + SiteID: + type: integer + description: Site reference (default 1) + VSName: + type: string + description: Value set name + VSDesc: + type: string + description: Value set description + responses: + '201': + description: User value set definition created + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/ValueSetDef' + /api/valueset/user/def/{id}: + get: + tags: + - ValueSets + summary: Get user value set definition by ID + description: Get value set definition from database (user-defined) + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: User value set definition details + content: + application/json: + schema: + type: object + properties: + status: + type: string + data: + $ref: '#/components/schemas/ValueSetDef' + put: + tags: + - ValueSets + summary: Update user value set definition + description: Update value set definition in database (user-defined) + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + SiteID: + type: integer + description: Site reference + VSName: + type: string + description: Value set name + VSDesc: + type: string + description: Value set description + responses: + '200': + description: User value set definition updated + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + data: + $ref: '#/components/schemas/ValueSetDef' + delete: + tags: + - ValueSets + summary: Delete user value set definition + description: Delete value set definition from database (user-defined) + security: + - bearerAuth: [] + parameters: + - name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: User value set definition deleted + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT token from login endpoint + cookieAuth: + type: apiKey + in: cookie + name: token + description: JWT token stored in HTTP-only cookie + schemas: + SuccessResponse: + type: object + properties: + status: + type: string + example: success + message: + type: string + code: + type: integer + example: 200 + ErrorResponse: + type: object + properties: + status: + type: string + example: error + message: + type: string + errors: + type: object + DashboardSummary: + type: object + properties: + pendingOrders: + type: integer + todayResults: + type: integer + criticalResults: + type: integer + activePatients: + type: integer + LoginRequest: + type: object + required: + - username + - password + properties: + username: + type: string + example: labuser01 + password: + type: string + format: password + example: secret123 + LoginResponse: + type: object + properties: + status: + type: string + example: success + code: + type: integer + example: 200 + message: + type: string + example: Login successful + RegisterRequest: + type: object + required: + - username + - password + - email + properties: + username: + type: string + password: + type: string + format: password + email: + type: string + format: email + full_name: + type: string + Patient: + type: object + required: + - PatientID + - Sex + - NameFirst + - Birthdate + properties: + PatientID: + type: string + maxLength: 30 + pattern: ^[A-Za-z0-9]+$ + description: Internal patient identifier + AlternatePID: + type: string + maxLength: 30 + pattern: ^[A-Za-z0-9]+$ + Prefix: + type: string + maxLength: 10 + enum: + - Mr + - Mrs + - Ms + - Dr + - Prof + Sex: + type: string + enum: + - '1' + - '2' + description: '1: Female, 2: Male' + NameFirst: + type: string + minLength: 1 + maxLength: 60 + pattern: ^[A-Za-z'\. ]+$ + NameMiddle: + type: string + minLength: 1 + maxLength: 60 + NameMaiden: + type: string + minLength: 1 + maxLength: 60 + NameLast: + type: string + minLength: 1 + maxLength: 60 + Suffix: + type: string + maxLength: 10 + Birthdate: + type: string + format: date-time + description: ISO 8601 UTC datetime + PlaceOfBirth: + type: string + maxLength: 100 + Citizenship: + type: string + maxLength: 100 + Street_1: + type: string + maxLength: 255 + Street_2: + type: string + maxLength: 255 + Street_3: + type: string + maxLength: 255 + ZIP: + type: string + maxLength: 10 + pattern: ^[0-9]+$ + Phone: + type: string + pattern: ^\+?[0-9]{8,15}$ + MobilePhone: + type: string + pattern: ^\+?[0-9]{8,15}$ + EmailAddress1: + type: string + format: email + maxLength: 100 + EmailAddress2: + type: string + format: email + maxLength: 100 + PatIdt: + $ref: '#/components/schemas/PatientIdentifier' + LinkTo: + type: array + description: Array of linked patient references + items: + $ref: '#/components/schemas/LinkedPatient' + Custodian: + $ref: '#/components/schemas/Custodian' + DeathIndicator: + type: string + enum: + - 'Y' + - 'N' + description: 'Y: Yes (deceased), N: No (alive)' + TimeOfDeath: + type: string + format: date-time + description: ISO 8601 UTC datetime of death + PatCom: + type: string + description: Patient comment/notes + PatAtt: + type: array + description: Patient address entries + items: + $ref: '#/components/schemas/PatAttEntry' + Province: + type: integer + description: Province AreaGeoID (foreign key to areageo table) + ProvinceLabel: + type: string + description: Province name (resolved from areageo) + City: + type: integer + description: City AreaGeoID (foreign key to areageo table) + CityLabel: + type: string + description: City name (resolved from areageo) + Country: + type: string + maxLength: 10 + description: Country ISO 3-letter code (e.g., IDN, USA) + CountryLabel: + type: string + description: Country name (resolved from valueset) + Race: + type: string + maxLength: 100 + MaritalStatus: + type: string + enum: + - A + - B + - D + - M + - S + - W + description: 'A: Annulled, B: Separated, D: Divorced, M: Married, S: Single, W: Widowed' + Religion: + type: string + maxLength: 100 + Ethnic: + type: string + maxLength: 100 + PatientIdentifier: + type: object + properties: + IdentifierType: + type: string + enum: + - KTP + - PASS + - SSN + - SIM + - KTAS + description: | + KTP: 16 digit numeric + PASS: alphanumeric max 9 + SSN: 9 digit numeric + SIM: 19-20 digit numeric + KTAS: 11 digit numeric + Identifier: + type: string + maxLength: 255 + LinkedPatient: + type: object + description: Linked patient reference + properties: + InternalPID: + type: integer + description: Internal patient ID of the linked patient + PatientID: + type: string + description: Patient ID of the linked patient + Custodian: + type: object + description: Patient custodian/guardian + properties: + InternalPID: + type: integer + description: Internal patient ID of the custodian + PatientID: + type: string + description: Patient ID of the custodian + PatAttEntry: + type: object + description: Patient address/attorney entry + properties: + Address: + type: string + description: Address text + PatientListResponse: + type: object + properties: + status: + type: string + example: success + data: + type: array + items: + $ref: '#/components/schemas/Patient' + pagination: + type: object + properties: + page: + type: integer + perPage: + type: integer + total: + type: integer + PatientVisit: + type: object + properties: + InternalPVID: + type: integer + description: Primary key (auto-generated) + PVID: + type: string + description: Visit ID (auto-generated with DV prefix if not provided) + InternalPID: + type: integer + description: Reference to patient + EpisodeID: + type: string + description: Episode identifier + SiteID: + type: integer + description: Site reference + 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 + AccountID: + type: integer + Discipline: + type: object + properties: + id: + type: integer + DisciplineName: + type: string + DisciplineCode: + type: string + Department: + type: object + properties: + id: + type: integer + DeptName: + type: string + DeptCode: + type: string + SiteID: + type: integer + Workstation: + type: object + properties: + id: + type: integer + WorkstationName: + type: string + WorkstationCode: + type: string + SiteID: + type: integer + DepartmentID: + type: integer + 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 + FormulaInput: + type: string + description: Input variables for calculated tests + FormulaCode: + type: string + description: Formula expression for calculated tests + testdefcal: + type: array + description: Calculated test details (only for CALC type) + items: + type: object + testdefgrp: + type: array + description: Group members (only for GROUP type) + items: + type: object + testmap: + type: array + description: Test mappings + items: + $ref: '#/components/schemas/TestMap' + refnum: + type: array + description: Numeric reference ranges (optional). Mutually exclusive with reftxt - a test can only have ONE reference type. + items: + type: object + properties: + RefNumID: + type: integer + NumRefType: + type: string + enum: + - NMRC + - THOLD + description: NMRC=Numeric range, THOLD=Threshold + NumRefTypeLabel: + type: string + RangeType: + type: string + RangeTypeLabel: + type: string + Sex: + type: string + SexLabel: + type: string + LowSign: + type: string + LowSignLabel: + type: string + HighSign: + type: string + HighSignLabel: + type: string + High: + type: number + format: float + Low: + type: number + format: float + AgeStart: + type: integer + AgeEnd: + type: integer + Flag: + type: string + Interpretation: + type: string + reftxt: + type: array + description: Text reference ranges (optional). Mutually exclusive with refnum - a test can only have ONE reference type. + items: + type: object + properties: + RefTxtID: + type: integer + TxtRefType: + type: string + enum: + - TEXT + - VSET + description: TEXT=Free text, VSET=Value set + TxtRefTypeLabel: + type: string + Sex: + type: string + SexLabel: + type: string + AgeStart: + type: integer + AgeEnd: + type: integer + RefTxt: + type: string + Flag: + type: string + examples: + TEST_numeric: + summary: Technical test with numeric reference + value: + TestSiteID: 1 + SiteID: 1 + TestSiteCode: GLU + TestSiteName: Glucose + TestType: TEST + DisciplineID: 2 + DepartmentID: 2 + ResultType: NMRIC + RefType: NMRC + Unit1: mg/dL + ReqQty: 300 + ReqQtyUnit: uL + Decimal: 0 + Method: Hexokinase + SeqScr: 11 + SeqRpt: 11 + VisibleScr: 1 + VisibleRpt: 1 + CountStat: 1 + refnum: + - RefNumID: 1 + NumRefType: NMRC + NumRefTypeLabel: Numeric + RangeType: REF + RangeTypeLabel: Reference Range + Sex: '2' + SexLabel: Male + LowSign: GE + LowSignLabel: '>=' + HighSign: LE + HighSignLabel: <= + Low: 70 + High: 100 + AgeStart: 18 + AgeEnd: 99 + Flag: 'N' + Interpretation: Normal + TEST_threshold: + summary: Technical test with threshold reference (panic) + value: + TestSiteID: 2 + SiteID: 1 + TestSiteCode: GLU + TestSiteName: Glucose + TestType: TEST + DisciplineID: 2 + DepartmentID: 2 + ResultType: NMRIC + RefType: THOLD + Unit1: mg/dL + Decimal: 0 + Method: Hexokinase + SeqScr: 11 + SeqRpt: 11 + VisibleScr: 1 + VisibleRpt: 1 + CountStat: 1 + refnum: + - RefNumID: 2 + NumRefType: THOLD + NumRefTypeLabel: Threshold + RangeType: PANIC + RangeTypeLabel: Panic Range + Sex: '1' + SexLabel: Female + LowSign: LT + LowSignLabel: < + High: 40 + AgeStart: 0 + AgeEnd: 120 + Flag: L + Interpretation: Critical Low + TEST_text: + summary: Technical test with text reference + value: + TestSiteID: 3 + SiteID: 1 + TestSiteCode: STAGE + TestSiteName: Disease Stage + TestType: TEST + DisciplineID: 1 + DepartmentID: 1 + ResultType: VSET + RefType: TEXT + SeqScr: 50 + SeqRpt: 50 + VisibleScr: 1 + VisibleRpt: 1 + CountStat: 1 + reftxt: + - RefTxtID: 1 + TxtRefType: TEXT + TxtRefTypeLabel: Text + Sex: '2' + SexLabel: Male + AgeStart: 18 + AgeEnd: 99 + RefTxt: NORM=Normal;HYPO=Hypochromic;MACRO=Macrocytic + Flag: 'N' + PARAM: + summary: Parameter test + value: + TestSiteID: 4 + SiteID: 1 + TestSiteCode: HEIGHT + TestSiteName: Height + TestType: PARAM + DisciplineID: 10 + ResultType: NMRIC + Unit1: cm + Decimal: 0 + SeqScr: 40 + SeqRpt: 40 + VisibleScr: 1 + VisibleRpt: 0 + CountStat: 0 + CALC: + summary: Calculated test with reference + value: + TestSiteID: 5 + SiteID: 1 + TestSiteCode: EGFR + TestSiteName: eGFR + TestType: CALC + DisciplineID: 2 + DepartmentID: 2 + Unit1: mL/min/1.73m2 + Decimal: 0 + SeqScr: 20 + SeqRpt: 20 + VisibleScr: 1 + VisibleRpt: 1 + CountStat: 0 + testdefcal: + - TestCalID: 1 + DisciplineID: 2 + DepartmentID: 2 + FormulaInput: CREA,AGE,GENDER + FormulaCode: CKD_EPI(CREA,AGE,GENDER) + Unit1: mL/min/1.73m2 + Decimal: 0 + refnum: + - RefNumID: 5 + NumRefType: NMRC + NumRefTypeLabel: Numeric + RangeType: REF + RangeTypeLabel: Reference Range + Sex: '1' + SexLabel: Female + LowSign: GE + LowSignLabel: '>=' + HighSign: LE + HighSignLabel: <= + Low: 10 + High: 20 + AgeStart: 18 + AgeEnd: 120 + Flag: 'N' + Interpretation: Normal + GROUP: + summary: Panel/Profile test + value: + TestSiteID: 6 + SiteID: 1 + TestSiteCode: LIPID + TestSiteName: Lipid Panel + TestType: GROUP + DisciplineID: 2 + DepartmentID: 2 + SeqScr: 51 + SeqRpt: 51 + VisibleScr: 1 + VisibleRpt: 1 + CountStat: 1 + testdefgrp: + - TestGrpID: 1 + Member: 100 + TestSiteCode: CHOL + TestSiteName: Total Cholesterol + - TestGrpID: 2 + Member: 101 + TestSiteCode: TG + TestSiteName: Triglycerides + TITLE: + summary: Section header + value: + TestSiteID: 7 + SiteID: 1 + TestSiteCode: CHEM_HEADER + TestSiteName: '--- CHEMISTRY ---' + TestType: TITLE + DisciplineID: 2 + DepartmentID: 2 + SeqScr: 100 + SeqRpt: 100 + VisibleScr: 1 + VisibleRpt: 1 + CountStat: 0 + TestMap: + type: object + properties: + TestMapID: + type: integer + 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 + 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 + 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 + SID: + type: string + description: Order ID reference + SampleID: + type: string + description: Sample ID (same as OrderID) + Result: + type: string + description: Test result value + nullable: true + 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/clqms_database.dbml b/docs/clqms_database.dbml deleted file mode 100644 index edd357c..0000000 --- a/docs/clqms_database.dbml +++ /dev/null @@ -1,640 +0,0 @@ -// CLQMS Database Schema -// Generated from app/Models/ directory -// Database Markup Language (DBML) for dbdiagram.io and other tools - -// ============================================ -// TABLE 1: Patient Management -// ============================================ - -Table patient { - InternalPID int [pk, increment] - PatientID varchar(255) - AlternatePID varchar(255) - Prefix varchar(50) - NameFirst varchar(255) - NameMiddle varchar(255) - NameMaiden varchar(255) - NameLast varchar(255) - Suffix varchar(50) - NameAlias varchar(255) - Sex varchar(10) - Birthdate datetime - PlaceOfBirth varchar(255) - Street_1 varchar(255) - Street_2 varchar(255) - Street_3 varchar(255) - City varchar(100) - Province varchar(100) - ZIP varchar(20) - Country varchar(100) - EmailAddress1 varchar(255) - EmailAddress2 varchar(255) - Phone varchar(50) - MobilePhone varchar(50) - AccountNumber varchar(100) - Race varchar(50) - MaritalStatus varchar(50) - Religion varchar(50) - Ethnic varchar(50) - Citizenship varchar(100) - DeathIndicator boolean - TimeOfDeath datetime - Custodian int [ref: > patient.InternalPID] - LinkTo int [ref: > patient.InternalPID] - CreateDate datetime [not null] - DelDate datetime -} - -Table patidt { - PatIdtID int [pk, increment] - InternalPID int [not null, ref: > patient.InternalPID] - IdentifierType varchar(100) - Identifier varchar(255) - EffectiveDate datetime - ExpirationDate datetime - CreateDate datetime [not null] - DelDate datetime -} - -Table patcom { - PatComID int [pk, increment] - InternalPID int [not null, ref: > patient.InternalPID] - Comment text - CreateDate datetime [not null] - EndDate datetime -} - -Table patatt { - PatAttID int [pk, increment] - InternalPID int [not null, ref: > patient.InternalPID] - UserID int - Address text - CreateDate datetime [not null] - DelDate datetime -} - -// ============================================ -// TABLE 2: Visit Management -// ============================================ - -Table patvisit { - InternalPVID int [pk, increment] - InternalPID int [not null, ref: > patient.InternalPID] - EpisodeID int - PVID varchar(100) - CreateDate datetime [not null] - EndDate datetime - ArchivedDate datetime - DelDate datetime -} - -Table patvisitadt { - PVADTID int [pk, increment] - InternalPVID int [not null, ref: > patvisit.InternalPVID] - LocationID int [ref: > location.LocationID] - ADTCode varchar(50) - AttDoc varchar(255) - RefDoc varchar(255) - AdmDoc varchar(255) - CnsDoc varchar(255) - CreateDate datetime [not null] - EndDate datetime - ArchivedDate datetime - DelDate datetime -} - -Table patdiag { - InternalPVID int [pk, increment] - InternalPVID int [not null, ref: > patvisit.InternalPVID] - InternalPID int [not null, ref: > patient.InternalPID] - DiagCode varchar(50) - Diagnosis varchar(255) - CreateDate datetime [not null] - EndDate datetime - ArchivedDate datetime - DelDate datetime -} - -// ============================================ -// TABLE 3: Organization Structure -// ============================================ - -Table account { - AccountID int [pk, increment] - AccountName varchar(255) - Initial varchar(50) - Street_1 varchar(255) - Street_2 varchar(255) - Street_3 varchar(255) - City varchar(100) - Province varchar(100) - ZIP varchar(20) - Country varchar(100) - AreaCode varchar(20) - EmailAddress1 varchar(255) - EmailAddress2 varchar(255) - Phone varchar(50) - Fax varchar(50) - Parent int [ref: > account.AccountID] - CreateDate datetime [not null] - EndDate datetime -} - -Table site { - SiteID int [pk, increment] - AccountID int [not null, ref: > account.AccountID] - Parent int [ref: > site.SiteID] - SiteTypeID int - SiteClassID int - SiteCode varchar(50) - SiteName varchar(255) - ME varchar(50) - CreateDate datetime [not null] - EndDate datetime -} - -Table department { - DepartmentID int [pk, increment] - DisciplineID int [ref: > discipline.DisciplineID] - SiteID int [ref: > site.SiteID] - DepartmentCode varchar(50) - DepartmentName varchar(255) - CreateDate datetime [not null] - EndDate datetime -} - -Table discipline { - DisciplineID int [pk, increment] - SiteID int [ref: > site.SiteID] - Parent int [ref: > discipline.DisciplineID] - DisciplineCode varchar(50) - DisciplineName varchar(255) - CreateDate datetime [not null] - EndDate datetime -} - -Table workstation { - WorkstationID int [pk, increment] - DepartmentID int [ref: > department.DepartmentID] - LinkTo int [ref: > workstation.WorkstationID] - EquipmentID int - WorkstationCode varchar(50) - WorkstationName varchar(255) - Type varchar(50) - Enable boolean - CreateDate datetime [not null] - EndDate datetime -} - -// ============================================ -// TABLE 4: Location Management -// ============================================ - -Table location { - LocationID int [pk, increment] - SiteID int [not null, ref: > site.SiteID] - Parent int [ref: > location.LocationID] - LocCode varchar(50) - LocFull varchar(255) - Description text - LocType varchar(50) - CreateDate datetime [not null] - EndDate datetime -} - -Table locationaddress { - LocationID int [pk, ref: > location.LocationID] - Province int [ref: > areageo.AreaGeoID] - City int [ref: > areageo.AreaGeoID] - Street1 varchar(255) - Street2 varchar(255) - PostCode varchar(20) - GeoLocationSystem varchar(50) - GeoLocationData text - Phone varchar(50) - Email varchar(255) - CreateDate datetime [not null] - EndDate datetime -} - -Table areageo { - AreaGeoID int [pk, increment] - Parent int [ref: > areageo.AreaGeoID] - AreaCode varchar(50) - Class varchar(50) - AreaName varchar(255) -} - -// ============================================ -// TABLE 5: Test Management -// ============================================ - -Table testdefsite { - TestSiteID int [pk, increment] - SiteID int [not null, ref: > site.SiteID] - TestSiteCode varchar(50) - TestSiteName varchar(255) - TestType varchar(50) // TEST, PARAM, CALC, GROUP, TITLE - Description text - SeqScr int - SeqRpt int - IndentLeft int - FontStyle varchar(50) - VisibleScr boolean - VisibleRpt boolean - CountStat boolean - CreateDate datetime [not null] - StartDate datetime - EndDate datetime -} - -Table testdeftech { - TestTechID int [pk, increment] - TestSiteID int [not null, ref: > testdefsite.TestSiteID] - DisciplineID int [ref: > discipline.DisciplineID] - DepartmentID int [ref: > department.DepartmentID] - VSet int - ResultType varchar(50) // NM, TX, DT, TM, VS, HL7 - RefType varchar(50) // NUM, TXT, VSET - ReqQty decimal(10,4) - ReqQtyUnit varchar(20) - Unit1 varchar(50) - Factor decimal(10,6) - Unit2 varchar(50) - Decimal int - CollReq text - Method varchar(255) - ExpectedTAT int - CreateDate datetime [not null] - EndDate datetime -} - -Table testdefcal { - TestCalID int [pk, increment] - TestSiteID int [not null, ref: > testdefsite.TestSiteID] - DisciplineID int [ref: > discipline.DisciplineID] - DepartmentID int [ref: > department.DepartmentID] - FormulaInput varchar(500) - FormulaCode text - RefType varchar(50) - Unit1 varchar(50) - Factor decimal(10,6) - Unit2 varchar(50) - Decimal int - Method varchar(255) - CreateDate datetime [not null] - EndDate datetime -} - -Table testdefgrp { - TestGrpID int [pk, increment] - TestSiteID int [not null, ref: > testdefsite.TestSiteID] - Member int [ref: > testdefsite.TestSiteID] - CreateDate datetime [not null] - EndDate datetime -} - -Table testmap { - TestMapID int [pk, increment] - TestSiteID int [not null, ref: > testdefsite.TestSiteID] - ConDefID int [ref: > containerdef.ConDefID] - HostType varchar(50) - HostID varchar(100) - HostDataSource varchar(100) - HostTestCode varchar(100) - HostTestName varchar(255) - ClientType varchar(50) - ClientID varchar(100) - ClientDataSource varchar(100) - ClientTestCode varchar(100) - ClientTestName varchar(255) - CreateDate datetime [not null] - EndDate datetime -} - -// ============================================ -// TABLE 6: Reference Ranges -// ============================================ - -Table refnum { - RefNumID int [pk, increment] - SiteID int [not null, ref: > site.SiteID] - TestSiteID int [not null, ref: > testdefsite.TestSiteID] - SpcType varchar(50) - Sex varchar(10) - Criteria varchar(255) - AgeStart int - AgeEnd int - NumRefType varchar(50) // NR, CR - RangeType varchar(50) // LL-UL, LL, UL, ABS - LowSign varchar(5) - Low decimal(15,5) - HighSign varchar(5) - High decimal(15,5) - Display varchar(50) - Flag varchar(10) - Interpretation text - Notes text - CreateDate datetime [not null] - StartDate datetime - EndDate datetime -} - -Table reftxt { - RefTxtID int [pk, increment] - SiteID int [not null, ref: > site.SiteID] - TestSiteID int [not null, ref: > testdefsite.TestSiteID] - SpcType varchar(50) - Sex varchar(10) - Criteria varchar(255) - AgeStart int - AgeEnd int - TxtRefType varchar(50) // TX, VS - RefTxt text - Flag varchar(10) - Notes text - CreateDate datetime [not null] - StartDate datetime - EndDate datetime -} - -Table refvset { - RefVSetID int [pk, increment] - SiteID int [not null, ref: > site.SiteID] - TestSiteID int [not null, ref: > testdefsite.TestSiteID] - SpcType varchar(50) - Sex varchar(10) - AgeStart int - AgeEnd int - RefTxt varchar(255) - CreateDate datetime [not null] - EndDate datetime -} - -Table refthold { - RefTHoldID int [pk, increment] - SiteID int [not null, ref: > site.SiteID] - TestSiteID int [not null, ref: > testdefsite.TestSiteID] - SpcType varchar(50) - Sex varchar(10) - AgeStart int - AgeEnd int - Threshold decimal(15,5) - BelowTxt text - AboveTxt text - GrayzoneLow decimal(15,5) - GrayzoneHigh decimal(15,5) - GrayzoneTxt text - CreateDate datetime [not null] - EndDate datetime -} - -// ============================================ -// TABLE 7: Specimen Management -// ============================================ - -Table specimen { - InternalSID int [pk, increment] - SID varchar(17) [not null, unique] - SiteID int [not null, ref: > site.SiteID] - OrderID varchar(13) - ConDefID int [ref: > containerdef.ConDefID] - Parent int [ref: > specimen.InternalSID] - Qty decimal(10,4) - Unit varchar(20) - GenerateBy varchar(100) - SchDateTime datetime - CreateDate datetime [not null] - EndDate datetime - ArchiveDate datetime -} - -Table specimenstatus { - SpcStaID int [pk, increment] - SID varchar(17) [not null, ref: > specimen.SID] - OrderID varchar(13) - CurrSiteID int [ref: > site.SiteID] - CurrLocID int [ref: > location.LocationID] - UserID int - SpcAct varchar(50) - ActRes varchar(50) - SpcStatus varchar(50) - Qty decimal(10,4) - Unit varchar(20) - SpcCon varchar(50) - Comment text - Origin varchar(100) - GeoLocationSystem varchar(50) - GeoLocationData text - DIDType varchar(50) - DID varchar(100) - CreateDate datetime [not null] - EndDate datetime - ArchiveDate datetime -} - -Table specimencollection { - SpcColID int [pk, increment] - SpcStaID int [not null, ref: > specimenstatus.SpcStaID] - SpRole varchar(50) - ColMethod varchar(50) - BodySite varchar(50) - CntSize varchar(50) - FastingVolume decimal(10,4) - ColStart datetime - ColEnd datetime - CreateDate datetime [not null] - EndDate datetime - ArchiveDate datetime -} - -Table specimenprep { - SpcPrpID int [pk, increment] - SpcStaID int [not null, ref: > specimenstatus.SpcStaID] - Description text - Method varchar(255) - Additive varchar(100) - AddQty decimal(10,4) - AddUnit varchar(20) - PrepStart datetime - PrepEnd datetime - CreateDate datetime [not null] - EndDate datetime - ArchiveDate datetime -} - -Table containerdef { - ConDefID int [pk, increment] - SiteID int [not null, ref: > site.SiteID] - ConCode varchar(50) - ConName varchar(255) - ConDesc text - Additive varchar(100) - ConClass varchar(50) - Color varchar(50) - CreateDate datetime [not null] - EndDate datetime -} - -// ============================================ -// TABLE 8: Order Management -// ============================================ - -Table ordertest { - InternalOID int [pk, increment] - OrderID varchar(13) [not null, unique] - PlacerID varchar(100) - InternalPID int [not null, ref: > patient.InternalPID] - SiteID int [ref: > site.SiteID] - PVADTID int [ref: > patvisitadt.PVADTID] - ReqApp varchar(100) - Priority varchar(50) - TrnDate datetime - EffDate datetime - CreateDate datetime [not null] - EndDate datetime - ArchiveDate datetime - DelDate datetime -} - -Table patres { - ResultID int [pk, increment] - SiteID int [ref: > site.SiteID] - OrderID varchar(13) - InternalSID int [ref: > specimen.InternalSID] - SID varchar(17) - SampleID varchar(100) - TestSiteID int [ref: > testdefsite.TestSiteID] - WorkstationID int [ref: > workstation.WorkstationID] - EquipmentID int - RefNumID int [ref: > refnum.RefNumID] - RefTxtID int [ref: > reftxt.RefTxtID] - TestSiteCode varchar(50) - AspCnt int - Result text - SampleType varchar(50) - ResultDateTime datetime - CreateDate datetime [not null] - EndDate datetime - ArchiveDate datetime - DelDate datetime -} - -// ============================================ -// TABLE 9: Contact Management -// ============================================ - -Table contact { - ContactID int [pk, increment] - NameFirst varchar(255) - NameLast varchar(255) - Title varchar(100) - Initial varchar(50) - Birthdate datetime - EmailAddress1 varchar(255) - EmailAddress2 varchar(255) - Phone varchar(50) - MobilePhone1 varchar(50) - MobilePhone2 varchar(50) - Specialty varchar(100) - SubSpecialty varchar(100) - CreateDate datetime [not null] - EndDate datetime -} - -Table contactdetail { - ContactDetID int [pk, increment] - ContactID int [not null, ref: > contact.ContactID] - SiteID int [ref: > site.SiteID] - OccupationID int [ref: > occupation.OccupationID] - ContactCode varchar(50) - ContactEmail varchar(255) - JobTitle varchar(100) - Department varchar(100) - ContactStartDate datetime - ContactEndDate datetime -} - -Table medicalspecialty { - SpecialtyID int [pk, increment] - Parent int [ref: > medicalspecialty.SpecialtyID] - SpecialtyText varchar(255) - Title varchar(100) - CreateDate datetime [not null] - EndDate datetime -} - -Table occupation { - OccupationID int [pk, increment] - OccCode varchar(50) - OccText varchar(255) - Description text - CreateDate datetime [not null] -} - -// ============================================ -// TABLE 10: Value Sets -// ============================================ - -Table valuesetdef { - VSetID int [pk, increment] - SiteID int [not null, ref: > site.SiteID] - VSName varchar(255) - VSDesc text - CreateDate datetime [not null] - EndDate datetime -} - -Table valueset { - VID int [pk, increment] - SiteID int [not null, ref: > site.SiteID] - VSetID int [not null, ref: > valuesetdef.VSetID] - VCategory varchar(100) - VOrder int - VValue varchar(255) - VDesc varchar(255) - CreateDate datetime [not null] - EndDate datetime -} - -// ============================================ -// TABLE 11: System / Counter -// ============================================ - -Table counter { - CounterID int [pk, increment] - CounterValue bigint - CounterStart bigint - CounterEnd bigint - CounterReset varchar(50) - CreateDate datetime [not null] - EndDate datetime -} - -Table edgeres { - EdgeResID int [pk, increment] - SiteID int [ref: > site.SiteID] - InstrumentID int - SampleID varchar(100) - PatientID varchar(100) - Payload text - Status varchar(50) - AutoProcess boolean - ProcessedAt datetime - ErrorMessage text - CreateDate datetime [not null] - EndDate datetime - ArchiveDate datetime - DelDate datetime -} - -Table zones { - id int [pk, increment] - name varchar(255) - code varchar(50) - type varchar(50) - description text - status varchar(50) - created_at datetime - updated_at datetime -} diff --git a/docs/orders.yaml b/docs/orders.yaml deleted file mode 100644 index 444caf0..0000000 --- a/docs/orders.yaml +++ /dev/null @@ -1,265 +0,0 @@ -/api/ordertest: - get: - tags: [Orders] - summary: List orders - security: - - bearerAuth: [] - parameters: - - name: page - in: query - schema: - type: integer - - name: perPage - in: query - schema: - type: integer - - name: InternalPID - in: query - schema: - type: integer - description: Filter by internal patient ID - - name: OrderStatus - in: query - schema: - type: string - enum: [ORD, SCH, ANA, VER, REV, REP] - description: | - ORD: Ordered - SCH: Scheduled - ANA: Analysis - VER: Verified - REV: Reviewed - REP: Reported - - name: include - in: query - schema: - type: string - enum: [details] - description: Include specimens and tests in response - 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/orders.yaml#/OrderTest' - - post: - tags: [Orders] - 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/orders.yaml#/OrderTest' - '400': - description: Validation error - '500': - description: Server error - - patch: - tags: [Orders] - summary: Update order - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - OrderID - properties: - OrderID: - type: string - 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/orders.yaml#/OrderTest' - - delete: - tags: [Orders] - 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: [Orders] - summary: Update order status - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - OrderID - - OrderStatus - properties: - OrderID: - type: string - OrderStatus: - type: string - enum: [ORD, SCH, ANA, VER, REV, REP] - description: | - ORD: Ordered - SCH: Scheduled - ANA: Analysis - VER: Verified - REV: Reviewed - REP: Reported - responses: - '200': - description: Order status updated - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '../components/schemas/orders.yaml#/OrderTest' - -/api/ordertest/{id}: - get: - tags: [Orders] - 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/orders.yaml#/OrderTest' diff --git a/docs/organization.yaml b/docs/organization.yaml deleted file mode 100644 index 0093e04..0000000 --- a/docs/organization.yaml +++ /dev/null @@ -1,707 +0,0 @@ -/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/organization.yaml#/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/organization.yaml#/Site' - responses: - '201': - description: Site created - - patch: - tags: [Organization] - summary: Update site - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - SiteName: - type: string - SiteCode: - type: string - AccountID: - type: integer - responses: - '200': - description: Site updated - - delete: - tags: [Organization] - summary: Delete site - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - responses: - '200': - description: Site deleted - -/api/organization/site/{id}: - get: - tags: [Organization] - summary: Get site by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Site details - -/api/organization/discipline: - get: - tags: [Organization] - summary: List disciplines - security: - - bearerAuth: [] - responses: - '200': - description: List of disciplines - - post: - tags: [Organization] - summary: Create discipline - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '../components/schemas/organization.yaml#/Discipline' - responses: - '201': - description: Discipline created - - patch: - tags: [Organization] - summary: Update discipline - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - DisciplineName: - type: string - DisciplineCode: - type: string - responses: - '200': - description: Discipline updated - - delete: - tags: [Organization] - summary: Delete discipline - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - responses: - '200': - description: Discipline deleted - -/api/organization/discipline/{id}: - get: - tags: [Organization] - summary: Get discipline by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Discipline details - -/api/organization/department: - get: - tags: [Organization] - summary: List departments - security: - - bearerAuth: [] - responses: - '200': - description: List of departments - - post: - tags: [Organization] - summary: Create department - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '../components/schemas/organization.yaml#/Department' - responses: - '201': - description: Department created - - patch: - tags: [Organization] - summary: Update department - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - DeptName: - type: string - DeptCode: - type: string - SiteID: - type: integer - responses: - '200': - description: Department updated - - delete: - tags: [Organization] - summary: Delete department - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - responses: - '200': - description: Department deleted - -/api/organization/department/{id}: - get: - tags: [Organization] - summary: Get department by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Department details - -/api/organization/workstation: - get: - tags: [Organization] - summary: List workstations - security: - - bearerAuth: [] - responses: - '200': - description: List of workstations - - post: - tags: [Organization] - summary: Create workstation - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '../components/schemas/organization.yaml#/Workstation' - responses: - '201': - description: Workstation created - - patch: - tags: [Organization] - summary: Update workstation - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - WorkstationName: - type: string - WorkstationCode: - type: string - SiteID: - type: integer - DepartmentID: - type: integer - responses: - '200': - description: Workstation updated - - delete: - tags: [Organization] - summary: Delete workstation - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - id - properties: - id: - type: integer - responses: - '200': - description: Workstation deleted - -/api/organization/workstation/{id}: - get: - tags: [Organization] - summary: Get workstation by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - responses: - '200': - description: Workstation details - -# HostApp -/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/organization.yaml#/HostApp' - - post: - tags: [Organization] - summary: Create host application - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '../components/schemas/organization.yaml#/HostApp' - responses: - '201': - description: Host application created - - patch: - tags: [Organization] - summary: Update host application - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - HostAppID - properties: - HostAppID: - type: string - HostAppName: - type: string - SiteID: - type: integer - responses: - '200': - description: Host application updated - - 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/organization.yaml#/HostApp' - -# HostComPara -/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/organization.yaml#/HostComPara' - - post: - tags: [Organization] - summary: Create host communication parameters - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '../components/schemas/organization.yaml#/HostComPara' - responses: - '201': - description: Host communication parameters created - - patch: - tags: [Organization] - summary: Update host communication parameters - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - HostAppID - properties: - HostAppID: - type: string - HostIP: - type: string - HostPort: - type: string - HostPwd: - type: string - responses: - '200': - description: Host communication parameters updated - - 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/organization.yaml#/HostComPara' - -# CodingSys -/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/organization.yaml#/CodingSys' - - post: - tags: [Organization] - summary: Create coding system - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '../components/schemas/organization.yaml#/CodingSys' - responses: - '201': - description: Coding system created - - patch: - tags: [Organization] - summary: Update coding system - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - CodingSysID - properties: - CodingSysID: - type: integer - CodingSysAbb: - type: string - FullText: - type: string - Description: - type: string - responses: - '200': - description: Coding system updated - - 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/organization.yaml#/CodingSys' diff --git a/docs/patient-visits.yaml b/docs/patient-visits.yaml deleted file mode 100644 index 888d424..0000000 --- a/docs/patient-visits.yaml +++ /dev/null @@ -1,519 +0,0 @@ -/api/patvisit: - get: - tags: [Patient Visits] - 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/patient-visit.yaml#/PatientVisit' - total: - type: integer - description: Total number of records - page: - type: integer - description: Current page number - per_page: - type: integer - description: Number of records per page - - post: - tags: [Patient Visits] - summary: Create patient visit - description: | - Creates a new patient visit. PVID is auto-generated with 'DV' prefix if not provided. - Can optionally include PatDiag (diagnosis) and PatVisitADT (ADT information). - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - InternalPID - properties: - PVID: - type: string - description: Visit ID (auto-generated with DV prefix if not provided) - InternalPID: - type: integer - description: Patient ID (required) - EpisodeID: - type: string - description: Episode identifier - SiteID: - type: integer - description: Site reference - PatDiag: - type: object - description: Optional diagnosis information - properties: - DiagCode: - type: string - Diagnosis: - type: string - PatVisitADT: - type: object - description: Optional ADT information - properties: - ADTCode: - type: string - enum: [A01, A02, A03, A04, A08] - LocationID: - type: integer - AttDoc: - type: integer - RefDoc: - type: integer - AdmDoc: - type: integer - CnsDoc: - type: integer - responses: - '201': - description: Visit created successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: object - properties: - PVID: - type: string - InternalPVID: - type: integer - - patch: - tags: [Patient Visits] - summary: Update patient visit - description: | - Updates an existing patient visit. InternalPVID is required. - Can update main visit data, PatDiag, and add new PatVisitADT records. - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - InternalPVID - properties: - InternalPVID: - type: integer - description: Visit ID (required) - PVID: - type: string - InternalPID: - type: integer - EpisodeID: - type: string - SiteID: - type: integer - PatDiag: - type: object - description: Diagnosis information (will update if exists) - properties: - DiagCode: - type: string - Diagnosis: - type: string - PatVisitADT: - type: array - description: Array of ADT records to add (new records only) - items: - type: object - properties: - ADTCode: - type: string - enum: [A01, A02, A03, A04, A08] - LocationID: - type: integer - AttDoc: - type: integer - RefDoc: - type: integer - AdmDoc: - type: integer - CnsDoc: - type: integer - sequence: - type: integer - description: Used for ordering multiple ADT records - responses: - '200': - description: Visit updated successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: object - properties: - PVID: - type: string - InternalPVID: - type: integer - - delete: - tags: [Patient Visits] - summary: Delete patient visit - security: - - bearerAuth: [] - responses: - '200': - description: Visit deleted successfully - -/api/patvisit/{id}: - get: - tags: [Patient Visits] - summary: Get visit by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: string - description: PVID (visit identifier like DV00001) - responses: - '200': - description: Visit details - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '../components/schemas/patient-visit.yaml#/PatientVisit' - -/api/patvisit/patient/{patientId}: - get: - tags: [Patient Visits] - summary: Get visits by patient ID - security: - - bearerAuth: [] - parameters: - - name: patientId - in: path - required: true - schema: - type: integer - description: Internal Patient ID (InternalPID) - responses: - '200': - description: Patient visits list - content: - application/json: - schema: - type: object - properties: - status: - type: string - data: - type: array - items: - $ref: '../components/schemas/patient-visit.yaml#/PatientVisit' - -/api/patvisitadt: - post: - tags: [Patient Visits] - summary: Create ADT record - description: Create a new Admission/Discharge/Transfer record - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '../components/schemas/patient-visit.yaml#/PatVisitADT' - responses: - '201': - description: ADT record created successfully - content: - application/json: - schema: - $ref: '../components/schemas/common.yaml#/SuccessResponse' - - patch: - tags: [Patient Visits] - summary: Update ADT record - description: Update an existing ADT record - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '../components/schemas/patient-visit.yaml#/PatVisitADT' - responses: - '200': - description: ADT record updated successfully - content: - application/json: - schema: - $ref: '../components/schemas/common.yaml#/SuccessResponse' - - delete: - tags: [Patient Visits] - summary: Delete ADT visit (soft delete) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - PVADTID - properties: - PVADTID: - type: integer - description: ADT record ID to delete - responses: - '200': - description: ADT visit deleted successfully - -/api/patvisitadt/visit/{visitId}: - get: - tags: [Patient Visits] - summary: Get ADT history by visit ID - description: Retrieve the complete Admission/Discharge/Transfer history for a visit, including all locations and doctors - security: - - bearerAuth: [] - parameters: - - name: visitId - in: path - required: true - schema: - type: integer - description: Internal Visit ID (InternalPVID) - responses: - '200': - description: ADT history retrieved successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: ADT history retrieved - data: - type: array - items: - type: object - properties: - PVADTID: - type: integer - InternalPVID: - type: integer - ADTCode: - type: string - enum: [A01, A02, A03, A04, A08] - LocationID: - type: integer - LocationName: - type: string - AttDoc: - type: integer - AttDocFirstName: - type: string - AttDocLastName: - type: string - RefDoc: - type: integer - RefDocFirstName: - type: string - RefDocLastName: - type: string - AdmDoc: - type: integer - AdmDocFirstName: - type: string - AdmDocLastName: - type: string - CnsDoc: - type: integer - CnsDocFirstName: - type: string - CnsDocLastName: - type: string - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time - delete: - tags: [Patient Visits] - summary: Delete ADT visit (soft delete) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - required: - - PVADTID - properties: - PVADTID: - type: integer - description: ADT record ID to delete - responses: - '200': - description: ADT visit deleted successfully - -/api/patvisitadt/{id}: - get: - tags: [Patient Visits] - summary: Get ADT record by ID - description: Retrieve a single ADT record by its ID, including location and doctor details - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: ADT record ID (PVADTID) - responses: - '200': - description: ADT record retrieved successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - example: ADT record retrieved - data: - type: object - properties: - PVADTID: - type: integer - InternalPVID: - type: integer - ADTCode: - type: string - enum: [A01, A02, A03, A04, A08] - LocationID: - type: integer - LocationName: - type: string - AttDoc: - type: integer - AttDocFirstName: - type: string - AttDocLastName: - type: string - RefDoc: - type: integer - RefDocFirstName: - type: string - RefDocLastName: - type: string - AdmDoc: - type: integer - AdmDocFirstName: - type: string - AdmDocLastName: - type: string - CnsDoc: - type: integer - CnsDocFirstName: - type: string - CnsDocLastName: - type: string - CreateDate: - type: string - format: date-time - EndDate: - type: string - format: date-time diff --git a/docs/testmap.yaml b/docs/testmap.yaml deleted file mode 100644 index 8e958b4..0000000 --- a/docs/testmap.yaml +++ /dev/null @@ -1,503 +0,0 @@ -/api/test/testmap: - get: - tags: [Tests] - summary: List all test mappings (unique groupings) - security: - - bearerAuth: [] - responses: - '200': - description: List of unique test mapping groupings - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: array - items: - type: object - properties: - HostType: - type: string - HostID: - type: string - HostName: - type: string - ClientType: - type: string - ClientID: - type: string - ClientName: - type: string - - post: - tags: [Tests] - summary: Create test mapping (header only) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestSiteID: - type: integer - description: Test Site ID (required) - HostType: - type: string - description: Host type code - HostID: - type: string - description: Host identifier - ClientType: - type: string - description: Client type code - ClientID: - type: string - description: Client identifier - details: - type: array - description: Optional detail records to create - items: - type: object - properties: - HostTestCode: - type: string - HostTestName: - type: string - ConDefID: - type: integer - ClientTestCode: - type: string - ClientTestName: - type: string - required: - - TestSiteID - responses: - '201': - description: Test mapping created - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: integer - description: Created TestMapID - - patch: - tags: [Tests] - summary: Update test mapping - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestMapID: - type: integer - description: Test Map ID (required) - TestSiteID: - type: integer - HostType: - type: string - HostID: - type: string - ClientType: - type: string - ClientID: - type: string - required: - - TestMapID - responses: - '200': - description: Test mapping updated - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: integer - description: Updated TestMapID - - delete: - tags: [Tests] - summary: Soft delete test mapping (cascades to details) - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestMapID: - type: integer - description: Test Map ID to delete (required) - required: - - TestMapID - responses: - '200': - description: Test mapping deleted successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: success - message: - type: string - data: - type: integer - description: Deleted TestMapID - '404': - description: Test mapping not found or already deleted - -/api/test/testmap/{id}: - get: - tags: [Tests] - summary: Get test mapping by ID with details - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Test Map ID - responses: - '200': - description: Test mapping details with nested detail records - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '../components/schemas/tests.yaml#/TestMap' - '404': - description: Test mapping not found - -/api/test/testmap/by-testsite/{testSiteID}: - get: - tags: [Tests] - summary: Get test mappings by test site with details - security: - - bearerAuth: [] - parameters: - - name: testSiteID - in: path - required: true - schema: - type: integer - description: Test Site ID - responses: - '200': - description: List of test mappings with details for the test site - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '../components/schemas/tests.yaml#/TestMap' - -/api/test/testmap/detail: - get: - tags: [Tests] - summary: List test mapping details - security: - - bearerAuth: [] - parameters: - - name: TestMapID - in: query - schema: - type: integer - description: Filter by TestMapID - responses: - '200': - description: List of test mapping details - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '../components/schemas/tests.yaml#/TestMapDetail' - - post: - tags: [Tests] - summary: Create test mapping detail - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestMapID: - type: integer - description: Test Map ID (required) - HostTestCode: - type: string - HostTestName: - type: string - ConDefID: - type: integer - ClientTestCode: - type: string - ClientTestName: - type: string - required: - - TestMapID - responses: - '201': - description: Test mapping detail created - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: integer - description: Created TestMapDetailID - - patch: - tags: [Tests] - summary: Update test mapping detail - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestMapDetailID: - type: integer - description: Test Map Detail ID (required) - TestMapID: - type: integer - HostTestCode: - type: string - HostTestName: - type: string - ConDefID: - type: integer - ClientTestCode: - type: string - ClientTestName: - type: string - required: - - TestMapDetailID - responses: - '200': - description: Test mapping detail updated - - delete: - tags: [Tests] - summary: Soft delete test mapping detail - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - TestMapDetailID: - type: integer - description: Test Map Detail ID to delete (required) - required: - - TestMapDetailID - responses: - '200': - description: Test mapping detail deleted - -/api/test/testmap/detail/{id}: - get: - tags: [Tests] - summary: Get test mapping detail by ID - security: - - bearerAuth: [] - parameters: - - name: id - in: path - required: true - schema: - type: integer - description: Test Map Detail ID - responses: - '200': - description: Test mapping detail - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - $ref: '../components/schemas/tests.yaml#/TestMapDetail' - -/api/test/testmap/detail/by-testmap/{testMapID}: - get: - tags: [Tests] - summary: Get test mapping details by test map ID - security: - - bearerAuth: [] - parameters: - - name: testMapID - in: path - required: true - schema: - type: integer - description: Test Map ID - responses: - '200': - description: List of test mapping details - content: - application/json: - schema: - type: object - properties: - status: - type: string - message: - type: string - data: - type: array - items: - $ref: '../components/schemas/tests.yaml#/TestMapDetail' - -/api/test/testmap/detail/batch: - post: - tags: [Tests] - summary: Batch create test mapping details - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: array - items: - type: object - properties: - TestMapID: - type: integer - HostTestCode: - type: string - HostTestName: - type: string - ConDefID: - type: integer - ClientTestCode: - type: string - ClientTestName: - type: string - responses: - '200': - description: Batch create results - - patch: - tags: [Tests] - summary: Batch update test mapping details - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: array - items: - type: object - properties: - TestMapDetailID: - type: integer - TestMapID: - type: integer - HostTestCode: - type: string - HostTestName: - type: string - ConDefID: - type: integer - ClientTestCode: - type: string - ClientTestName: - type: string - responses: - '200': - description: Batch update results - - delete: - tags: [Tests] - summary: Batch delete test mapping details - security: - - bearerAuth: [] - requestBody: - required: true - content: - application/json: - schema: - type: array - items: - type: integer - description: TestMapDetailIDs to delete - responses: - '200': - description: Batch delete results diff --git a/docs/use_case_260214.md b/docs/use_case_260214.md deleted file mode 100644 index a9287c4..0000000 --- a/docs/use_case_260214.md +++ /dev/null @@ -1,514 +0,0 @@ -Here is the converted Markdown format of the Use Case document. I have structured it with headers and lists to make it easily parsable by an AI agent. - -```markdown -# Use Case Document - -## Use Case – Authentication -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-01 | -| **Use Case Name** | Authentication | -| **Aktor Utama** | Admin Lab / Clerk, Analis Lab, Analis Lab Senior, Super User, Phlebotomist Lab, Perawat, DSPK/Konsulen, Supervisor Lab, Manajer Lab, Database Administrator, System Administrator | -| **Aktor Sekunder** | - | -| **Tujuan** | Verifikasi identitas pengguna, yang mencoba mengakses sistem, memastikan bahwa mereka adalah orang yang mereka klaim. Bertindak sebagai mekanisme keamanan primer untuk mencegah akses tidak sah, melindungi data, dan mengurangi risiko seperti pencurian identitas dan pelanggaran keamanan. | -| **Prasyarat** | Data pengguna sudah terdefinisi dalam sistem sebagai User atau Contact. | - -### Alur Utama -1. Aktor klik tombol Login. -2. System menampilkan login dialog yang terdiri dari User ID dan Password. -3. Aktor memasukkan email address sebagai User ID. -4. System memeriksa email address di table User, SiteStatus, Contact dan ContactDetail: - - Jika Aktor menggunakan email pribadi, maka System menampilkan pilihan sites dimana Aktor memiliki akses. Aktor, kemudian memilih salah satu site. - - Jika Aktor menggunakan email site, maka System langsung mengarahkan ke site yang bersangkutan. -5. Aktor memasukkan password. -6. System memeriksa kebenaran User ID dan password. -7. System memeriksa role dan menu apa saja yang bisa diakses Aktor. -8. System menampilkan halaman utama dengan menu sesuai role Aktor. - -### Alur Alternatif -- - -### Alur Pengecualian -* **Aktor tidak terdaftar:** - * System menampilkan pesan: “Unregistered user, please contact system administrator”. -* **Aktor ditemukan tetapi:** - * **Disabled:** System menampilkan pesan: “Disabled user, please contact system administrator”. - * **Password expired:** System menampilkan pesan: “Your password is expired, please contact system administrator”. - * **Password salah:** - * System menampilkan pesan: “Invalid login”. - * System menghitung jumlah percobaan login password yang gagal dan mencatat dalam Audit log (device dimana login attempt dilakukan, waktu). - * System menghentikan proses login untuk User ID tersebut selama x jam dan menampilkan pesan, ”Please try again in x hours or contact system administrator”. - -### Kondisi Akhir -* Aktor masuk ke halaman utama dan mendapat akses menu-menu system yang sesuai. -* Audit mencatat User ID, waktu, device dimana Aktor melakukan login. - ---- - -## Use Case – Patient Registration -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-02a | -| **Use Case Name** | Patient Registration | -| **Aktor Utama** | Admin Lab / Clerk, Analis Lab, Analis Lab Senior, Super User, Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Mencatatkan data demografi pasien baru ke oleh System | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi dalam System.
3. Pasien menunjukkan identitas yang sah (kartu identitas, atau rujukan). | - -### Alur Utama -1. Aktor membuka halaman Patient Management – Patient Registration. -2. Aktor memasukkan PID. -3. System memeriksa apakah PID sudah ada. -4. System meminta detail pasien (nama, tanggal lahir, jenis kelamin, informasi kontak, nomor identitas, dst). -5. Aktor memasukkan informasi demografis pasien, dengan mandatory data: - - patient.NameFirst - - patient.Gender - - patient.Birthdate -6. Jika Aktor memasukkan `patidt.IdentifierType` dan `patidt.Identifier`, maka System memeriksa apakah sudah ada record pasien yang menggunakan Identifier yang sama. -7. System membuat record baru di `patvisitadt` dengan `patvisitadt.Code: A04` (Register), mengkonfirmasi registrasi berhasil dan menampilkan ringkasan pasien. -8. Aktor memberikan konfirmasi pendaftaran kepada Pasien (misalnya, slip cetak atau ID digital – barcode, QRIS, dll). - -### Alur Alternatif -* **Record pasien sudah ada:** - 1. Aktor memasukkan PID. - 2. System mengambil record yang sudah ada dan menampilkan data di halaman Patient Management – Patient Search & Update. - 3. Aktor memperbarui data jika diperlukan. - 4. Sistem menyimpan perubahan dan membuat record baru di `patvisitadt` dengan `patvisitadt.Code: A08` (Update patient information). - -### Alur Pengecualian -* **Mandatory data tidak ada:** - * System menolak menyimpan record. - * Aktor diminta untuk melengkapi, setidaknya mandatory data. -* **Record pasien tidak ada tetapi ditemukan record yang menggunakan `patidt.IdentifierType` dan `patidt.Identifier` yang sama:** - * System menampilkan pesan ’Multiple IDs found”. - * System menampilkan records dengan `patidt.IdentifierType` dan `patidt.Identifier` yang sama. - * Aktor melakukan review. - * Aktor memilih salah satu dari kemungkinan berikut: - 1. Melanjutkan membuat record pasien baru, mengabaikan record ganda. - 2. Melanjutkan membuat record pasien baru, kemudian menggabungkan record pasien (lihat UC-02b). - 3. Membatalkan pendaftaran. - -### Kondisi Akhir -* Record pasien dibuat atau diperbarui di System. -* PID pasien tersedia untuk test ordering & tracing. -* Audit mencatat bahwa record dibuat/diperbarui secara manual, User ID yang mendaftarkan/memperbarui data pasien, device dimana, kapan, dan data apa yang dimasukkan. - ---- - -## Use Case – Patient Link -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-02b | -| **Use Case Name** | Patient Link | -| **Aktor Utama** | Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Link (menghubungkan) satu atau beberapa record (PID) pasien (source) dengan record pasien lainnya (destination). PatientID destination adalah surviving entity, yang akan digunakan dalam semua aktivitas laboratorium. | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi dalam System.
3. PID source dan destination telah tercatat dalam System.
4. PID source dan destination memiliki `patidt.IdentifierType` dan `patidt.Identifier` yang sama atau nama, alamat dan tanggal lahir yang sama. | - -### Alur Utama -1. Aktor membuka halaman Patient Management - Patient Link. -2. Aktor mencari PID menggunakan: - - `patidt.IdentifierType` dan `patidt.Identifier` - - Nama, alamat dan tanggal lahir -3. System menampilkan semua PID dengan `patidt.IdentifierType` dan `patidt.Identifier` dan/atau nama, alamat dan tanggal lahir yang sama. -4. Aktor memilih dan menentukan satu PID untuk menjadi destination. (Lihat Alur Pengecualian). -5. Aktor memilih dan menentukan satu atau lebih, PID yang menjadi source. (Lihat Alur Pengecualian). -6. Aktor menghubungkan PID-PID tersebut dengan menekan tombol Link. -7. System meminta konfirmasi dari Aktor dengan menampilkan pesan,” Please confirm to link these patient records”. Disertai pilihan “Confirm” dan “Cancel”. -8. Aktor mengkonfirmasi Patient Link dengan menekan tombol Confirm. -9. System melakukan: - - Membuat record baru di `patvisitadt` dengan `patvisitadt.Code: A24` (Link Patient Information). - - Mengkonfirmasi Patient Link berhasil. - - Menampilkan ringkasan PID yang dihubungkan. - -### Alur Alternatif -- - -### Alur Pengecualian -* **System menemukan bahwa suatu record pasien telah menjadi source, ditandai dengan field `patient.LinkTo` telah terisi dengan PID dari record lain (ditampilkan):** - * **Multiple link:** - * Aktor memilih dan menunjuk record tersebut sebagai source bagi PID yang berbeda. - * System menampilkan peringatan “Multiple link” di samping PID tersebut dan pilihan (check mark) tidak bisa dilakukan. - * **Multi-level Link:** - * Aktor memilih dan menunjuk record tersebut sebagai destination bagi PID yang berbeda. - * System menampilkan peringatan “Multi-level link” di samping PID tersebut dan pilihan (check mark) tidak bisa dilakukan. - * Jika semua atau satu-satunya PID mendapat peringatan tersebut maka, proses Patient Link sama sekali tidak bisa dilanjutkan. - * Jika ada PID lain yang tidak mendapat peringatan, maka proses Patient Link dilanjutkan atas PID tanpa peringatan. - -### Kondisi Akhir -* PID source terhubung dengan PID destination. -* Relasi source dengan test order dan lain-lain tidak berubah sebelum dan sesudah proses Patient Link. -* Semua test order milik PID source dan destination bisa ditampilkan dalam satu cumulative view/report. -* PID destination tersedia untuk test ordering & tracing. -* PID source tetap bisa dicari tetapi tidak bisa di-edit maupun digunakan untuk test ordering. -* Audit mencatat Patient Link dilakukan secara manual, waktu, User ID yang melakukan Patient Link serta device dimana aktivitas tersebut dilakukan. - ---- - -## Use Case – Patient Unlink -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-02c | -| **Use Case Name** | Patient Unlink | -| **Aktor Utama** | Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Melepaskan link antara source PID dan destination PID. | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi dalam System.
3. Pasien sudah pernah registrasi di System, ditandai dengan adanya PID dengan `patidt.IdentifierType` dan `patidt.Identifier` yang sama. | - -### Alur Utama -1. Aktor membuka halaman Patient Management – Patient Unlink. -2. Aktor mencari record pasien menggunakan PID. -3. System menampilkan PID berikut data demografinya dan semua linked PID. -4. Aktor uncheck source PID(s) yang hendak dilepaskan dari destination PID. -5. Aktor melepas hubungan PID-PID tersebut dengan menekan tombol Unlink. -6. System meminta konfirmasi dari Aktor dengan menampilkan pesan,” Please confirm to unlink these patient records”. Disertai pilihan “Confirm” dan “Cancel”. -7. Aktor mengkonfirmasi Patient Unink dengan menekan tombol Confirm. -8. System melakukan: - - Mengosongkan field `patient.LinkTo` dari source PID. - - Membuat record baru di `patvisitadt` dengan `patvisitadt.Code: A37` (Unlink Patient Information). - - Mengkonfirmasi Patient Unlink berhasil. - - Menampilkan ringkasan destination dan source PID yang unlinked. - -### Alur Alternatif -- - -### Alur Pengecualian -- - -### Kondisi Akhir -* Source PID aktif kembali, bisa diedit dan tersedia untuk test ordering & tracing. -* Unlink source terjadi bisa isi field LinkTo dikosongkan Kembali. -* Audit mencatat Patient Unlink dilakukan secara manual, waktu, User ID yang melakukan Patient Unlink dan device dimana aktivitas tersebut dilakukan. - ---- - -## Use Case – Patient Admission -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-03a | -| **Use Case Name** | Patient Admission | -| **Aktor Utama** | Admin Lab / Clerk, Analis Lab, Analis Lab Senior, Super User, Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Menerima pasien di fasyankes untuk perawatan atau observasi. | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi oleh System.
3. Record pasien tersedia di System, ditandai dengan adanya PID. | - -### Alur Utama -1. Aktor membuka halaman Patient Visit Management – Patient Admission. -2. Aktor memasukkan PID. -3. System memeriksa apakah PID ada. -4. System menampilkan data demografi pasien dan meminta data-data: - - **Mandatory data:** PVID, dokter, location. - - **Optional data:** EpisodeID, diagnosis (bisa lebih dari satu), lampiran-lampiran. -5. System membuat record baru di `patvisitadt` dengan `patvisitadt.Code: A01` (Admit), mengkonfirmasi admission berhasil dan menampilkan ringkasan admission. -6. Aktor memberikan konfirmasi admission kepada Pasien (misalnya, slip cetak atau ID digital – barcode, QRIS, dll). - -### Alur Alternatif -* **PID tidak ada:** - 1. System menampilkan pesan, “PID does not exist. Proceed to Patient Registration?”. - 2. Aktor memilih “Yes” dan System membuka halaman Patient Management – Patient Registration. - 3. Aktor melakukan activity patient registration dilanjutkan patient admission. -* **Pembaruan optional data:** - 1. Aktor membuka halaman Patient Visit Management – Admission Search & Update. - 2. Aktor memasukkan PVID. - 3. System mengambil record yang sudah ada. - 4. Aktor memperbarui data jika diperlukan. - 5. Sistem menyimpan perubahan. - -### Alur Pengecualian -* **Mandatory data tidak ada:** - * System menolak menyimpan record. - * Aktor diminta untuk melengkapi, setidaknya mandatory data. - -### Kondisi Akhir -* Kunjungan pasien ke fasyankes tercatat (patvisit records) di System, ditandai dengan adanya PVID dan direlasikan dengan dokter dan ruangan di fasyankes. -* Audit mencatat admission/perubahannya dilakukan secara manual, User ID yang melakukan, device dimana, kapan, dan data apa saja yang dimasukkan. - ---- - -## Use Case – Cancel Admission -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-03b | -| **Use Case Name** | Cancel Patient Admission | -| **Aktor Utama** | Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Membatalkan penerimaan pasien di fasyankes. Pembatalan bisa disebabkan: Data registrasi salah atau tidak lengkap, Cakupan asuransi tidak valid, Pasien menolak rawat inap, Pasien dialihkan, Permintaan rawat inap salah, Kondisi pasien berubah, Permintaan pasien, dll. | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi oleh System.
3. Patient Visit Record tersedia di System, ditandai dengan adanya PVID. | - -### Alur Utama -1. Aktor membuka halaman Patient Visit Management – Admission Search & Update. -2. Aktor memasukkan PVID. -3. System menampilkan data admission pasien. -4. Aktor mengkonfirmasi pembatalan admission ke pihak terkait dan melakukan pembatalan. -5. System membuat record baru di `patvisitadt` dengan `patvisitadt.Code: A11` (Cancel Admit), mengkonfirmasi cancel patient admission berhasil dan menampilkan ringkasan cancel patient admission. -6. Aktor memberikan konfirmasi cancel patient admission kepada pihak terkait (misalnya, slip cetak atau ID digital – barcode, QRIS, dll). - -### Alur Alternatif -- - -### Alur Pengecualian -- - -### Kondisi Akhir -* Cancel patient admission tercatat (patvisit records) di System, ditandai dengan record di `patvisitadt` dengan `patvisitadt.Code: A11`. -* Audit mencatat cancel patient admission dilakukan secara manual, User ID yang melakukan, device dimana, kapan, dan data apa yang dimasukkan. - ---- - -## Use Case – Change Attending Doctor -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-03c | -| **Use Case Name** | Change Attending Doctor | -| **Aktor Utama** | Admin Lab / Clerk, Analis Lab, Analis Lab Senior, Super User, Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Mengganti dokter yang bertanggung jawab atas pengobatan pasien (DPJP). | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi oleh System.
3. Patient Visit Record tersedia di System, ditandai dengan adanya PVID dan telah memiliki data Attending Doctor (`patvisitadt.AttDoc`). | - -### Alur Utama -1. Aktor membuka halaman Patient Visit Management – Admission Search & Update. -2. Aktor memasukkan PVID. -3. System menampilkan data admission pasien. -4. Aktor mengganti Attending Doctor. -5. System membuat record baru di `patvisitadt` dengan `patvisitadt.Code: A54` (Change Attending Doctor), mengkonfirmasi penggantian dokter berhasil dan menampilkan data admission yang telah diperbarui. - -### Alur Alternatif -- - -### Alur Pengecualian -- - -### Kondisi Akhir -* Penggantian Attending Doctor di System sehingga bisa dilakukan pelacakan Attending Doctor sekarang dan sebelumnya. -* Audit mencatat User ID yang melakukan perubahan Attending Doctor, device dimana perubahan dilakukan, kapan. - ---- - -## Use Case – Change Consulting Doctor -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-03d | -| **Use Case Name** | Change Consulting Doctor | -| **Aktor Utama** | Admin Lab / Clerk, Analis Lab, Analis Lab Senior, Super User, Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Mengganti dokter konsulen. | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi oleh System.
3. Patient Visit Record tersedia di System, ditandai dengan adanya PVID dan telah memiliki data Consulting Doctor (`patvisitadt.CnsDoc`). | - -### Alur Utama -1. Aktor membuka halaman Patient Visit Management – Admission Search & Update. -2. Aktor memasukkan PVID. -3. System menampilkan data admission pasien. -4. Aktor mengganti Consulting Doctor. -5. System membuat record baru di `patvisitadt` dengan `patvisitadt.Code: A61` (Change Consulting Doctor), mengkonfirmasi penggantian dokter berhasil dan menampilkan data admission yang telah diperbarui. - -### Alur Alternatif -- - -### Alur Pengecualian -- - -### Kondisi Akhir -* Penggantian Consulting Doctor di System sehingga bisa dilakukan pelacakan Consulting Doctor sekarang dan sebelumnya. -* Audit mencatat User ID yang melakukan perubahan Consulting Doctor, device dimana perubahan dilakukan, kapan. - ---- - -## Use Case – Patient Transfer -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-04 | -| **Use Case Name** | Patient Transfer | -| **Aktor Utama** | Admin Lab / Clerk, Analis Lab, Analis Lab Senior, Super User, Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Memindahkan pasien dari satu lokasi ke lokasi lainnya. | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi oleh System.
3. Patient Visit Record tersedia di System, ditandai dengan adanya PVID dan telah memiliki data Location ID (`patvisitadt.LocationID`). | - -### Alur Utama -1. Aktor membuka halaman Patient Visit Management – Transfer. -2. Aktor memasukkan PVID. -3. System menampilkan data admission pasien. -4. Aktor mengganti Location ID. -5. System membuat record baru di `patvisitadt` dengan `patvisitadt.Code: A02` (Patient Transfer), mengkonfirmasi perpindahan lokasi berhasil dan menampilkan data admission yang telah diperbarui. - -### Alur Alternatif -- - -### Alur Pengecualian -- - -### Kondisi Akhir -* Penggantian Location ID di System sehingga bisa dilakukan pelacakan Location ID sekarang dan sebelumnya. -* Audit mencatat User ID yang melakukan perubahan Location ID, device dimana perubahan dilakukan dan kapan. - ---- - -## Use Case – Patient Discharge -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-04a | -| **Use Case Name** | Patient Discharge | -| **Aktor Utama** | Admin Lab / Clerk, Analis Lab, Analis Lab Senior, Super User, Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Mengakhiri kunjungan pasien. Close billing. | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi oleh System.
3. Patient Visit Record tersedia di System, ditandai dengan adanya PVID. | - -### Alur Utama -1. Aktor membuka halaman Patient Visit Management – Discharge. -2. Aktor memasukkan PVID. -3. System memeriksa apakah PVID tersebut memiliki test order. -4. System memeriksa `orderstatus.OrderStatus` dari test order tsb. -5. System menampilkan data admission pasien. -6. Aktor mengisikan tanggal discharge. -7. System membuat record baru di `patvisitadt` dengan `patvisitadt.Code: A03` (Discharge), mengkonfirmasi discharge/end visit berhasil dan menampilkan data admission yang telah di-discharge. - -### Alur Alternatif -- - -### Alur Pengecualian -* **Open test order:** - * System menolak discharge, jika menemukan `orderstatus.OrderStatus` bernilai ”A” atau “IP” atau “SC” atau “HD”. - * Aktor diminta untuk menyelesaikan test order terkait. - -### Kondisi Akhir -* Discharge visit di System. -* Audit mencatat User ID yang melakukan discharge, device dimana discharge dilakukan dan kapan. -* Semua record terkait visit tersebut tidak bisa diedit/update lagi – data-data pada `patvisit`, `patdiag`, `patvisitbill`. Hal-hal berikut tidak bisa dilakukan lagi: - - Perpindahan lokasi dan/atau dokter. - - Test order. - - Billing is closed. -* **Cancel discharge:** - - Bisa dilakukan atas instruksi dari HIS, misalnya berupa ADT message. - - Oleh orang tertentu saja di lab. - - Tidak meng-update existing record tetapi men-trigger tambahan `patvisitadt` record dengan Code: A13 (cancel discharge). - ---- - -## Use Case – Cancel Discharge -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-04b | -| **Use Case Name** | Cancel Patient Discharge | -| **Aktor Utama** | Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Membatalkan Patient Discharge. Open billing. | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi oleh System.
3. Patient Visit Record tersedia di System, ditandai dengan adanya PVID dan telah discharge. | - -### Alur Utama -1. Aktor membuka halaman Patient Visit Management – Cancel Patient Discharge. -2. Aktor memasukkan PVID. -3. System menampilkan data admission pasien. -4. Aktor membatalkan discharge dengan menekan tombol Cancel Discharge. -5. System membuat record baru di `patvisitadt` dengan `patvisitadt.Code: A13` (Cancel Discharge), mengkonfirmasi cancel discharge berhasil dan menampilkan data admission yang telah dibatalkan discharge-nya. - -### Alur Alternatif -- - -### Alur Pengecualian -- - -### Kondisi Akhir -* Pembatalan discharge di System. -* Audit mencatat cancel discharge dilakukan secara manual, User ID yang melakukan, device dimana activity dilakukan dan kapan. -* Semua record terkait visit tersebut kembali bisa diedit/update lagi – data-data pada `patvisit`, `patdiag`, `patvisitbill`. Hal-hal berikut bisa dilakukan lagi: - - Perpindahan lokasi dan/atau dokter. - - Test order. - - Billing is re-open. - ---- - -## Use Case – Test Ordering -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-5a | -| **Use Case Name** | Test Ordering | -| **Aktor Utama** | Admin Lab / Clerk, Analis Lab, Analis Lab Senior, Super User, Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Membuat test order untuk pasien. | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi oleh System.
3. Patient Visit Record tersedia di System, ditandai dengan adanya PVID. | - -### Alur Utama -1. Aktor membuka halaman Test Ordering – New Test Order. -2. Aktor memasukkan PVID. -3. System menampilkan data demografi, daftar PVID pasien berikut daftar OrderID (OID) yang telah dibuat sebelumnya (menghindari test order berlebihan). -4. Aktor bisa menambahkan komentar dan/atau lampiran ke test order. -5. Aktor memilih test yang diperlukan. -6. Aktor bisa memilih mencetak labels segera setelah klik tombol Save, dengan mencentang Print Patient Label, Print Order Label, Print Specimen Label check boxes. -7. Aktor menyimpan test order dengan menekan tombol Save. -8. System secara otomatis memberi OID. -9. System otomatis membuat records di table specimens. -10. System, mengkonfirmasi test ordering berhasil dan menampilkan data test order berikut daftar SID. - -### Alur Alternatif -* **PVID belum ada:** - 1. System mengarahkan Aktor ke halaman Patient Visit Management – Patient Admission. - 2. Aktor melakukan activity patient admission. - 3. Aktir kembali ke test ordering. -* **Test ordering menggunakan PID:** - 1. Aktor membuka halaman Test Ordering – New Test Order. - 2. Aktor memasukkan PID. - 3. System menampilkan daftar PVID yang belum discharge. - 4. Aktor memilih salah satu PVID dan melanjutkan activity test ordering. -* **Future Order:** - 1. Aktor mengisi Effective Date (`ordertest.EffDate`) untuk menjadwalkan kapan test order mulai dikerjakan. - 2. Aktor menyimpan test order dengan menekan tombol Save. - 3. System memberikan OID yang sesuai dengan Effective Date. -* **OID sudah ada:** - 1. Aktor membuka halaman Test Ordering – Test Order Search & Update. - 2. Aktor memasukan OID. - 3. System menampilkan data-data test order. - 4. Aktor melakukan update dan menyimpannya. -* **Non patient option** (Not detailed in text). - -### Alur Pengecualian -- - -### Kondisi Akhir -* Test order terbentuk di System ditandai dengan adanya OID dengan status (`orderstatus.OrderStatus`) ”SC” (In process, scheduled). -* SID terbentuk dan specimen label bisa dicetak atau tercetak otomatis. -* Audit mencatat test order dilakukan secara manual, User ID yang melakukan, device dimana activity dilakukan dan kapan. - ---- - -## Use Case – Update Test Order -| **Field** | **Description** | -| :--- | :--- | -| **Use Case ID** | UC-5b | -| **Use Case Name** | Update Test Order | -| **Aktor Utama** | Admin Lab / Clerk, Analis Lab, Analis Lab Senior, Super User, Supervisor Lab, Manajer Lab | -| **Aktor Sekunder** | Pasien | -| **Tujuan** | Memperbarui test order untuk pasien. | -| **Prasyarat** | 1. System beroperasi dan dapat diakses.
2. Petugas pendaftaran telah terautentikasi oleh System.
3. Test order tersedia di System, ditandai dengan adanya OID. | - -### Alur Utama -1. Aktor membuka halaman Test Ordering – Test Order Search & Update. -2. Aktor memasukkan OID. -3. System menampilkan data-data test order. -4. Aktor melakukan update dan menyimpannya. -5. System, mengkonfirmasi update test order berhasil dan menampilkan data test order berikut daftar SID. - -### Alur Alternatif -* **PVID belum ada:** - 1. System mengarahkan Aktor ke halaman Patient Visit Management – Patient Admission. - 2. Aktor melakukan activity patient admission. - 3. Aktir kembali ke test ordering. -* **Non patient option** (Not detailed in text). - -### Alur Pengecualian -* **Test order tidak ada:** - * System menolak melakukan update dan menampilkan pesan,” Test order does not exists”. -* **Test order berstatus closed:** Ditandai dengan `ordertest.EndDate` memiliki value dan `orderstatus.OrderStatus` bernilai CL (Closed). - * System menolak melakukan update dan menampilkan pesan,” This test order is inaccessible”. -* **Test order berstatus archived:** Ditandai dengan `ordertest.ArchiveDate` memiliki value dan `orderstatus.OrderStatus` bernilai AC (Archived). - * System menolak melakukan update dan menampilkan pesan,” This test order is already archived”. -* **Test order berstatus deleted:** Ditandai dengan `ordertest.DelDate` memiliki value dan `orderstatus.OrderStatus` bernilai DL (Deleted). - * System menolak melakukan update dan menampilkan pesan,” This test order is already deleted”. -* **Update dilakukan dengan menghapus test yang telah ada hasilnya:** - * System menampilkan data-data test order. - * Aktor mengganti test yang telah ada hasilnya. - * System menolak melakukan update dan menampilkan pesan,” This test order is inaccessible”. - -### Kondisi Akhir -* Test order terbentuk di System ditandai dengan adanya OID dengan status (`orderstatus.OrderStatus`) ”SC” (In process, scheduled). -* SID terbentuk dan specimen label bisa dicetak atau tercetak otomatis. -* Audit mencatat test order dilakukan secara manual, User ID yang melakukan, device dimana activity dilakukan dan kapan. -``` \ No newline at end of file diff --git a/src/lib/api/auth.js b/src/lib/api/auth.js index 3136b32..a6f0f8f 100644 --- a/src/lib/api/auth.js +++ b/src/lib/api/auth.js @@ -1,4 +1,4 @@ -import { post } from './client.js'; +import { post, get } from './client.js'; /** * Authentication API endpoints @@ -33,5 +33,5 @@ export async function logout() { * @returns {Promise} */ export async function getCurrentUser() { - return post('/api/auth/check', {}); + return get('/api/auth/check'); } diff --git a/src/lib/api/client.js b/src/lib/api/client.js index ac74728..d333259 100644 --- a/src/lib/api/client.js +++ b/src/lib/api/client.js @@ -13,29 +13,18 @@ function getApiUrl() { } /** - * Base API client with JWT handling + * Base API client with cookie-based authentication * @param {string} endpoint - API endpoint (without base URL) * @param {Object} options - Fetch options * @returns {Promise} - JSON response */ export async function apiClient(endpoint, options = {}) { - // Get token from store - let token = null; - auth.subscribe((authState) => { - token = authState.token; - })(); - // Build headers const headers = { 'Content-Type': 'application/json', ...options.headers, }; - // Add Authorization header if token exists - if (token) { - headers['Authorization'] = `Bearer ${token}`; - } - // Build full URL using runtime config const url = `${getApiUrl()}${endpoint}`; @@ -43,6 +32,7 @@ export async function apiClient(endpoint, options = {}) { const response = await fetch(url, { ...options, headers, + credentials: 'include', }); // Handle 401 Unauthorized diff --git a/src/lib/api/reports.js b/src/lib/api/reports.js new file mode 100644 index 0000000..5ea6e60 --- /dev/null +++ b/src/lib/api/reports.js @@ -0,0 +1,44 @@ +import { config } from '$lib/stores/config.js'; + +/** + * Get the API URL from runtime config + * @returns {string} + */ +function getApiUrl() { + const runtimeUrl = config.getApiUrl(); + return runtimeUrl || import.meta.env.VITE_API_URL || ''; +} + +/** + * Generate lab report URL for an order + * @param {string|number} orderId - Order ID + * @returns {string} Report URL + */ +export function getReportUrl(orderId) { + return `${getApiUrl()}/api/reports/${orderId}`; +} + +/** + * Open report in new window + * @param {string|number} orderId - Order ID + * @param {string} [target='_blank'] - Window target + * @returns {Window|null} Window reference + */ +export function openReport(orderId, target = '_blank') { + const url = getReportUrl(orderId); + return window.open(url, target); +} + +/** + * Print report for an order + * @param {string|number} orderId - Order ID + */ +export function printReport(orderId) { + const url = getReportUrl(orderId); + const printWindow = window.open(url, '_blank'); + if (printWindow) { + printWindow.onload = () => { + printWindow.print(); + }; + } +} diff --git a/src/lib/api/results.js b/src/lib/api/results.js new file mode 100644 index 0000000..f99d8f7 --- /dev/null +++ b/src/lib/api/results.js @@ -0,0 +1,75 @@ +import { get, patch, del } from './client.js'; + +/** + * Fetch results with optional filters + * @param {Object} params - Query parameters + * @param {number} [params.order_id] - Filter by order ID + * @param {number} [params.patient_id] - Filter by patient ID + * @param {number} [params.page] - Page number + * @param {number} [params.per_page] - Items per page + * @returns {Promise} Results list response + */ +export async function fetchResults(params = {}) { + const query = new URLSearchParams(); + + if (params.order_id) query.append('order_id', params.order_id); + if (params.patient_id) query.append('patient_id', params.patient_id); + if (params.page) query.append('page', params.page); + if (params.per_page) query.append('per_page', params.per_page); + + const queryString = query.toString(); + return get(queryString ? `/api/results?${queryString}` : '/api/results'); +} + +/** + * Fetch a single result by ID + * @param {number} id - Result ID + * @returns {Promise} Result details + */ +export async function fetchResultById(id) { + return get(`/api/results/${id}`); +} + +/** + * Update a result value with auto-validation + * @param {number} id - Result ID + * @param {Object} data - Result data + * @param {string} data.Result - The result value + * @param {number} [data.RefNumID] - Reference range ID + * @param {string} [data.SampleType] - Sample type + * @param {number} [data.WorkstationID] - Workstation ID + * @param {number} [data.EquipmentID] - Equipment ID + * @returns {Promise} Updated result with flag + */ +export async function updateResult(id, data) { + return patch(`/api/results/${id}`, data); +} + +/** + * Delete a result (soft delete) + * @param {number} id - Result ID + * @returns {Promise} Success response + */ +export async function deleteResult(id) { + return del(`/api/results/${id}`); +} + +/** + * Fetch results by order ID + * @param {number} orderId - Order ID + * @returns {Promise} Results list for order + */ +export async function fetchResultsByOrder(orderId) { + return fetchResults({ order_id: orderId }); +} + +/** + * Fetch cumulative results by patient ID + * @param {number} patientId - Patient ID + * @param {number} [page] - Page number + * @param {number} [perPage] - Items per page + * @returns {Promise} Patient results history + */ +export async function fetchResultsByPatient(patientId, page = 1, perPage = 20) { + return fetchResults({ patient_id: patientId, page, per_page: perPage }); +} diff --git a/src/lib/stores/auth.js b/src/lib/stores/auth.js index 3a83f83..77442d3 100644 --- a/src/lib/stores/auth.js +++ b/src/lib/stores/auth.js @@ -1,59 +1,85 @@ import { writable } from 'svelte/store'; import { browser } from '$app/environment'; - -const STORAGE_KEY = 'auth_token'; +import { get } from '$lib/api/client.js'; /** - * Create auth store with localStorage persistence + * Create auth store with cookie-based authentication */ function createAuthStore() { - // Get initial state from localStorage (only in browser) - const getInitialState = () => { - if (!browser) { - return { token: null, user: null, isAuthenticated: false }; - } - const token = localStorage.getItem(STORAGE_KEY); - return { - token, - user: null, - isAuthenticated: !!token, - }; - }; - - const { subscribe, set, update } = writable(getInitialState()); + const { subscribe, set, update } = writable({ + user: null, + isAuthenticated: false, + loading: true, + }); return { subscribe, /** - * Set authentication data after login - * @param {string} token - JWT token + * Set user data after successful login + * Token is stored in HTTP-only cookie by backend * @param {Object} user - User object */ - login: (token, user) => { - if (browser) { - localStorage.setItem(STORAGE_KEY, token); - } - set({ token, user, isAuthenticated: true }); + login: (user) => { + set({ user, isAuthenticated: true, loading: false }); }, /** * Clear authentication data on logout */ logout: () => { - if (browser) { - localStorage.removeItem(STORAGE_KEY); - } - set({ token: null, user: null, isAuthenticated: false }); + set({ user: null, isAuthenticated: false, loading: false }); }, /** - * Update user data without changing token + * Update user data without changing auth status * @param {Object} user - Updated user object */ setUser: (user) => { update((state) => ({ ...state, user })); }, + + /** + * Check if user is authenticated via cookie + * @returns {Promise} + */ + checkAuth: async () => { + if (!browser) return false; + + try { + const response = await get('/api/auth/check'); + + // Backend returns user data nested under response.data + const userData = response.data || response; + if (response.status === 'success' && userData.userid) { + const user = { + id: userData.userid, + username: userData.username, + name: userData.NameFirst && userData.NameLast + ? `${userData.NameFirst} ${userData.NameLast}` + : userData.username, + ...userData + }; + set({ user, isAuthenticated: true, loading: false }); + return true; + } else { + set({ user: null, isAuthenticated: false, loading: false }); + return false; + } + } catch (error) { + console.error('Auth check failed:', error.message); + set({ user: null, isAuthenticated: false, loading: false }); + return false; + } + }, + + /** + * Set loading state + * @param {boolean} loading + */ + setLoading: (loading) => { + update((state) => ({ ...state, loading })); + }, }; } diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index b677767..d99210a 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -1,6 +1,7 @@
- + +
+

Dashboard

+ +
+ +
-
+ +
navigateTo('/orders')} + >
Pending Orders
-
24
-
Jan 1 - Feb 8
+
+ {#if loading} + + {:else} + {stats.pendingOrders} + {/if} +
+
Scheduled for analysis
-
+ + +
navigateTo('/results')} + >
Today's Results
-
156
-
↗︎ 14% more than yesterday
+
+ {#if loading} + + {:else} + {stats.todayResults} + {/if} +
+
Results entered today
-
+ + +
navigateTo('/results')} + >
Critical Results
-
3
+
+ {#if loading} + + {:else} + {stats.criticalResults} + {/if} +
Requires attention
-
+ + +
navigateTo('/patients')} + >
Active Patients
-
89
+
+ {#if loading} + + {:else} + {stats.activePatients} + {/if} +
Currently in system
- +
+
-

- - Orders Trend -

-
-

[Chart: Orders over time]

+
+

+ + Orders Trend +

+ +
+
+
+ +

Order analytics coming soon

+

Track orders over time

+
+ +
-

- - Results Volume -

-
-

[Chart: Results by department]

+
+

+ + Results Volume +

+ +
+
+
+ +

Results analytics coming soon

+

Results by test type

+
- +
-

- +

+ Recent Activity

-
    -
  • -
    -
    - -
    -
    -
    - -
    Order #12345 created
    -
    Patient: John Doe (P-1001)
    -
    -
    -
  • -
  • -
    -
    - -
    -
    -
    - -
    Result received
    -
    Sample: ABC123 - Instrument: CBC-M01
    -
    -
    -
  • -
  • -
    -
    - -
    -
    -
    - -
    Patient registered
    -
    Patient ID: P-1001 - Jane Smith
    -
    -
  • -
+ + {#if loading} +
+ +
+ {:else if recentActivity.length === 0} +
+ +

No recent activity

+
+ {:else} +
    + {#each recentActivity as activity, i} +
  • +
    +
    + +
    +
    +
    + +
    {activity.title}
    +
    {activity.description}
    +
    + {#if i < recentActivity.length - 1} +
    + {/if} +
  • + {/each} +
+ {/if}

diff --git a/src/routes/(app)/orders/OrderFormModal.svelte b/src/routes/(app)/orders/OrderFormModal.svelte index d2432ed..456351f 100644 --- a/src/routes/(app)/orders/OrderFormModal.svelte +++ b/src/routes/(app)/orders/OrderFormModal.svelte @@ -3,6 +3,7 @@ import Modal from '$lib/components/Modal.svelte'; import { ORDER_STATUS, ORDER_PRIORITY } from '$lib/api/orders.js'; import { fetchPatients } from '$lib/api/patients.js'; + import { fetchTests } from '$lib/api/tests.js'; import { success as toastSuccess, error as toastError } from '$lib/utils/toast.js'; import { User, FlaskConical, Building2, Hash, FileText, AlertCircle, Plus, X, Search, Beaker } from 'lucide-svelte'; @@ -40,7 +41,9 @@ let patientSearchResults = $state([]); let showPatientSearch = $state(false); let selectedPatient = $state(null); - let testInput = $state({ TestSiteID: '' }); + let testSearchQuery = $state(''); + let testSearchResults = $state([]); + let showTestSearch = $state(false); // Reset form when modal opens $effect(() => { @@ -82,6 +85,9 @@ } formError = ''; showPatientSearch = false; + testSearchQuery = ''; + testSearchResults = []; + showTestSearch = false; } }); @@ -112,21 +118,42 @@ patientSearchResults = []; } - function addTest() { - const testSiteId = parseInt(testInput.TestSiteID); - if (!testSiteId || isNaN(testSiteId)) { - formError = 'Please enter a valid Test Site ID'; - return; - } + async function searchTests() { + if (!testSearchQuery.trim()) return; + formLoading = true; + try { + const query = testSearchQuery.trim(); + const response = await fetchTests({ + TestSiteCode: query, + TestSiteName: query, + perPage: 10 + }); + testSearchResults = response.data || []; + showTestSearch = true; + } catch (err) { + toastError('Failed to search tests'); + testSearchResults = []; + } finally { + formLoading = false; + } + } + + function addTest(test) { // Check for duplicates - if (formData.Tests.some(t => t.TestSiteID === testSiteId)) { + if (formData.Tests.some(t => t.TestSiteID === test.TestSiteID)) { formError = 'Test already added'; return; } - formData.Tests = [...formData.Tests, { TestSiteID: testSiteId }]; - testInput.TestSiteID = ''; + formData.Tests = [...formData.Tests, { + TestSiteID: test.TestSiteID, + TestSiteCode: test.TestSiteCode, + TestSiteName: test.TestSiteName + }]; + testSearchQuery = ''; + testSearchResults = []; + showTestSearch = false; formError = ''; } @@ -181,12 +208,13 @@ const priorityOptions = Object.values(ORDER_PRIORITY); - +
+
{#if formError} @@ -386,55 +414,81 @@ {/if} - -
-
- - e.key === 'Enter' && (e.preventDefault(), addTest())} - /> + +
+
+
+ + e.key === 'Enter' && searchTests()} + /> +
+
- + + {#if showTestSearch && testSearchResults.length > 0} +
+ {#each testSearchResults as test (test.TestSiteID)} + + {/each} +
+ {:else if showTestSearch} +

No tests found

+ {/if}
{#if formData.Tests.length > 0} -
+
{#each formData.Tests as test, index (test.TestSiteID)} -
-
-
- {index + 1} -
-
-

Test Site ID

-

{test.TestSiteID}

-
+
+
+ {#if test.TestSiteCode} + {test.TestSiteCode} + {:else} + ID:{test.TestSiteID} + {/if} + + {test.TestSiteName || `Test #${test.TestSiteID}`} +
{/each}
{:else}
- +

No tests added yet

-

Enter a Test Site ID and click Add

+

Search and select tests above

{/if}
@@ -462,3 +516,10 @@ {/snippet} +
+ + diff --git a/src/routes/(app)/reports/+page.svelte b/src/routes/(app)/reports/+page.svelte new file mode 100644 index 0000000..53abe47 --- /dev/null +++ b/src/routes/(app)/reports/+page.svelte @@ -0,0 +1,311 @@ + + +
+ +
+

+ + Lab Reports +

+
+ Total: {totalItems} orders +
+
+ + +
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+ + +
+
+ {#if loading} +
+ +
+ {:else if orders.length === 0} +
+ +

No orders found

+
+ {:else} +
+ + + + + + + + + + + + + + {#each orders as order} + + + + + + + + + + {/each} + +
Order IDPatient IDVisit IDStatusPriorityCreatedActions
{order.OrderID}{order.InternalPID || '-'}{order.PatVisitID || '-'} + + {getStatusLabel(order.OrderStatus)} + + + {#if order.Priority === 'U'} + Urgent + {:else if order.Priority === 'S'} + Stat + {:else} + Routine + {/if} + + {order.CreateDate ? new Date(order.CreateDate).toLocaleDateString() : '-'} + +
+ + +
+
+
+ + + {#if totalPages > 1} +
+
+ + + Page {currentPage} of {totalPages} + + +
+
+ {/if} + {/if} +
+
+ + +
+
+

Order Status Pipeline

+
+ {#each orderStatuses as status} +
+ {status.label} +
+ {/each} +
+
+
+
+ + +{#if showReportModal && selectedOrderId} + +{/if} diff --git a/src/routes/(app)/reports/ReportViewerModal.svelte b/src/routes/(app)/reports/ReportViewerModal.svelte new file mode 100644 index 0000000..192b507 --- /dev/null +++ b/src/routes/(app)/reports/ReportViewerModal.svelte @@ -0,0 +1,137 @@ + + + + {#snippet children()} +
+ +
+
+ + Order: {orderId} +
+
+ + +
+
+ + +
+ {#if loading} +
+
+ +

Loading report...

+
+
+ {/if} + + {#if error} +
+
+
+ +
+

Report Error

+

{error}

+

Note: Reports are only available for orders that have been reported (REP status)

+
+
+ {:else} + + {/if} +
+
+ {/snippet} + + {#snippet footer()} + + + {/snippet} +
diff --git a/src/routes/(app)/results/+page.svelte b/src/routes/(app)/results/+page.svelte new file mode 100644 index 0000000..9459bc3 --- /dev/null +++ b/src/routes/(app)/results/+page.svelte @@ -0,0 +1,287 @@ + + +
+ +
+

+ + Results Entry +

+
+ Total: {totalItems} orders +
+
+ + +
+
+
+
+ Order ID + +
+ +
+ Patient ID + +
+ +
+ + +
+ +
+ + +
+
+
+
+ + +
+
+ {#if loading} +
+ +
+ {:else if orders.length === 0} +
+ +

No orders found

+
+ {:else} +
+ + + + + + + + + + + + + + {#each orders as order (order.OrderID)} + {@const statusInfo = getStatusInfo(order.OrderStatus)} + {@const priorityInfo = getPriorityInfo(order.Priority)} + {@const testCount = order.Tests?.length || 0} + {@const pendingCount = order.Tests?.filter(t => !t.Result || t.Result === '').length || 0} + + + + + + + + + + {/each} + +
Order IDPatientOrder DateStatusPriorityTestsActions
{order.OrderID} +
+ {order.PatientName || '-'} + ID: {order.InternalPID} +
+
+ {order.OrderDateTime ? new Date(order.OrderDateTime).toLocaleDateString() : '-'} + + {statusInfo.label} + + {priorityInfo.label} + +
+ {testCount} + {#if pendingCount > 0} + ({pendingCount} pending) + {:else} + + {/if} +
+
+ +
+
+ + + {#if totalPages > 1} +
+
+ + + Page {currentPage} of {totalPages} + + +
+
+ {/if} + {/if} +
+
+
+ + +{#if showEntryModal && selectedOrder} + +{/if} diff --git a/src/routes/(app)/results/ResultEntryModal.svelte b/src/routes/(app)/results/ResultEntryModal.svelte new file mode 100644 index 0000000..bceceea --- /dev/null +++ b/src/routes/(app)/results/ResultEntryModal.svelte @@ -0,0 +1,301 @@ + + + + {#snippet children()} +
+ +
+
+
+
+ + {order?.PatientName || 'Unknown'} + (ID: {order?.InternalPID}) +
+
+ + {order?.Tests?.length || 0} tests +
+
+
+ {#if pendingCount > 0} + {pendingCount} pending + {/if} + {#if savedCount > 0} + {savedCount} saved + {/if} +
+
+
+ + +
+ + + + + + + + + + + + + {#each results as result, index (result.ResultID)} + + + + + + + + + {/each} + +
CodeTest NameResultFlagReferenceUnit
{result.TestSiteCode} + {result.TestSiteName} + {#if result.error} +
{result.error}
+ {/if} +
+ + + {#if result.flag} + + {result.flag} + + {:else} + - + {/if} + {result.RefDisplay || '-'}{result.Unit1 || '-'}
+
+ + +
+
+ H + High +
+
+ L + Low +
+
+ + Normal +
+
+ Press Enter to move to next field +
+
+ + + {#if formLoading && saveProgress.total > 0} +
+ + Saving {saveProgress.current} of {saveProgress.total}... +
+ {/if} +
+ {/snippet} + + {#snippet footer()} + + + {/snippet} +
diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte index 3862bb2..3ffb95f 100644 --- a/src/routes/login/+page.svelte +++ b/src/routes/login/+page.svelte @@ -62,7 +62,13 @@ try { const response = await login(username, password); - auth.login(response.token, response.user); + + // Cookie is set by backend, now fetch user data + const isAuthenticated = await auth.checkAuth(); + + if (!isAuthenticated) { + throw new Error('Failed to verify authentication'); + } if (rememberMe) { localStorage.setItem('clqms_username', username); @@ -72,7 +78,7 @@ localStorage.setItem('clqms_remember', 'false'); } - goto('/dashboard'); + await goto('/dashboard'); } catch (err) { error = err.message || 'Login failed. Please try again.'; } finally {