refactor: Remove SpecimenType field from tests management

- Update API documentation to remove SpecimenType from examples

- Remove SpecimenType from tests API client

- Remove specimen type dropdown and handling from tests page
This commit is contained in:
mahdahar 2026-02-16 07:03:25 +07:00
parent f7a884577f
commit f917a0f018
3 changed files with 86 additions and 131 deletions

View File

@ -657,9 +657,11 @@ components:
TITLE: Section header TITLE: Section header
DisciplineID: DisciplineID:
type: integer type: integer
DisciplineName:
type: string
DepartmentID: DepartmentID:
type: integer type: integer
SpecimenType: DepartmentName:
type: string type: string
Unit: Unit:
type: string type: string
@ -736,28 +738,7 @@ components:
Flag: Flag:
type: string type: string
examples: examples:
TEST_simple: $1 Unit: mg/dL
summary: Technical test - no reference range
value:
id: 1
TestCode: GLU
TestName: Glucose
TestType: TEST
DisciplineID: 1
DepartmentID: 1
SpecimenType: SER
Unit: mg/dL
TEST_numeric_nmrc:
summary: Technical test - numeric reference (NMRC)
value:
id: 1
TestCode: GLU
TestName: Glucose
TestType: TEST
DisciplineID: 1
DepartmentID: 1
SpecimenType: SER
Unit: mg/dL
refnum: refnum:
- RefNumID: 1 - RefNumID: 1
NumRefType: NMRC NumRefType: NMRC
@ -767,9 +748,9 @@ components:
Sex: '2' Sex: '2'
SexLabel: Male SexLabel: Male
LowSign: GE LowSign: GE
LowSignLabel: '>= LowSignLabel: ">="
HighSign: LE HighSign: LE
HighSignLabel: '<=' HighSignLabel: "<="
Low: 70 Low: 70
High: 100 High: 100
AgeStart: 18 AgeStart: 18
@ -785,7 +766,6 @@ components:
TestType: TEST TestType: TEST
DisciplineID: 1 DisciplineID: 1
DepartmentID: 1 DepartmentID: 1
SpecimenType: SER
Unit: mg/dL Unit: mg/dL
refnum: refnum:
- RefNumID: 2 - RefNumID: 2
@ -796,23 +776,13 @@ components:
Sex: '1' Sex: '1'
SexLabel: Female SexLabel: Female
LowSign: LT LowSign: LT
LowSignLabel: '<' LowSignLabel: "<"
High: 40 High: 40
AgeStart: 0 AgeStart: 0
AgeEnd: 120 AgeEnd: 120
Flag: L Flag: L
Interpretation: Critical Low Interpretation: Critical Low
TEST_text_text: $1 Unit: null
summary: Technical test - text reference (TEXT)
value:
id: 1
TestCode: RBC_MORPH
TestName: RBC Morphology
TestType: TEST
DisciplineID: 1
DepartmentID: 1
SpecimenType: BLD
Unit: null
reftxt: reftxt:
- RefTxtID: 1 - RefTxtID: 1
TxtRefType: TEXT TxtRefType: TEXT
@ -832,7 +802,6 @@ components:
TestType: TEST TestType: TEST
DisciplineID: 1 DisciplineID: 1
DepartmentID: 1 DepartmentID: 1
SpecimenType: null
Unit: null Unit: null
reftxt: reftxt:
- RefTxtID: 2 - RefTxtID: 2
@ -853,19 +822,8 @@ components:
TestType: PARAM TestType: PARAM
DisciplineID: 1 DisciplineID: 1
DepartmentID: 1 DepartmentID: 1
SpecimenType: SER
Unit: mg/dL Unit: mg/dL
CALC_numeric_nmrc: $1 Unit: null
summary: Calculated test - numeric reference (NMRC)
value:
id: 3
TestCode: BUN_CR_RATIO
TestName: BUN/Creatinine Ratio
TestType: CALC
DisciplineID: 1
DepartmentID: 1
SpecimenType: SER
Unit: null
Formula: "BUN / Creatinine" Formula: "BUN / Creatinine"
refnum: refnum:
- RefNumID: 5 - RefNumID: 5
@ -876,26 +834,16 @@ components:
Sex: '1' Sex: '1'
SexLabel: Female SexLabel: Female
LowSign: GE LowSign: GE
LowSignLabel: '>= LowSignLabel: ">="
HighSign: LE HighSign: LE
HighSignLabel: '<=' HighSignLabel: "<="
Low: 10 Low: 10
High: 20 High: 20
AgeStart: 18 AgeStart: 18
AgeEnd: 120 AgeEnd: 120
Flag: N Flag: N
Interpretation: Normal Interpretation: Normal
CALC_numeric_thold: $1 Unit: null
summary: Calculated test - threshold reference (THOLD)
value:
id: 3
TestCode: BUN_CR_RATIO
TestName: BUN/Creatinine Ratio
TestType: CALC
DisciplineID: 1
DepartmentID: 1
SpecimenType: SER
Unit: null
Formula: "BUN / Creatinine" Formula: "BUN / Creatinine"
refnum: refnum:
- RefNumID: 6 - RefNumID: 6
@ -906,7 +854,7 @@ components:
Sex: '1' Sex: '1'
SexLabel: Female SexLabel: Female
LowSign: GT LowSign: GT
LowSignLabel: '>' LowSignLabel: ">"
Low: 20 Low: 20
AgeStart: 18 AgeStart: 18
AgeEnd: 120 AgeEnd: 120
@ -922,7 +870,6 @@ components:
TestType: GROUP TestType: GROUP
DisciplineID: 1 DisciplineID: 1
DepartmentID: 1 DepartmentID: 1
SpecimenType: SER
Unit: null Unit: null
TITLE: TITLE:
summary: Section header - no reference range allowed summary: Section header - no reference range allowed
@ -933,7 +880,6 @@ components:
TestType: TITLE TestType: TITLE
DisciplineID: 1 DisciplineID: 1
DepartmentID: 1 DepartmentID: 1
SpecimenType: null
Unit: null Unit: null
TestMap: TestMap:
@ -1952,6 +1898,68 @@ paths:
items: items:
$ref: '#/components/schemas/PatientVisit' $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}: /api/patvisitadt/visit/{visitId}:
get: get:
tags: [Patient Visits] tags: [Patient Visits]
@ -2026,8 +2034,6 @@ paths:
EndDate: EndDate:
type: string type: string
format: date-time format: date-time
$1
delete: delete:
tags: [Patient Visits] tags: [Patient Visits]
summary: Delete ADT visit (soft delete) summary: Delete ADT visit (soft delete)
@ -2122,7 +2128,7 @@ $1
type: string type: string
format: date-time format: date-time
$2/account/{id}: /api/organization/account/{id}:
get: get:
tags: [Organization] tags: [Organization]
summary: Get account by ID summary: Get account by ID
@ -2137,6 +2143,10 @@ $2/account/{id}:
responses: responses:
'200': '200':
description: Account details description: Account details
content:
application/json:
schema:
$ref: '#/components/schemas/Account'
# ======================================== # ========================================
# Organization - Site Routes # Organization - Site Routes

View File

@ -21,7 +21,6 @@ export async function createTest(data) {
VisibleScr: data.VisibleScr ? '1' : '0', VisibleScr: data.VisibleScr ? '1' : '0',
VisibleRpt: data.VisibleRpt ? '1' : '0', VisibleRpt: data.VisibleRpt ? '1' : '0',
// Type-specific fields // Type-specific fields
SpecimenType: data.SpecimenType,
Unit: data.Unit, Unit: data.Unit,
Formula: data.Formula, Formula: data.Formula,
// Reference ranges (only for TEST and CALC) // Reference ranges (only for TEST and CALC)
@ -44,7 +43,6 @@ export async function updateTest(data) {
VisibleScr: data.VisibleScr ? '1' : '0', VisibleScr: data.VisibleScr ? '1' : '0',
VisibleRpt: data.VisibleRpt ? '1' : '0', VisibleRpt: data.VisibleRpt ? '1' : '0',
// Type-specific fields // Type-specific fields
SpecimenType: data.SpecimenType,
Unit: data.Unit, Unit: data.Unit,
Formula: data.Formula, Formula: data.Formula,
// Reference ranges (only for TEST and CALC) // Reference ranges (only for TEST and CALC)

View File

@ -2,7 +2,6 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { fetchTests, createTest, updateTest, deleteTest } from '$lib/api/tests.js'; import { fetchTests, createTest, updateTest, deleteTest } from '$lib/api/tests.js';
import { fetchDisciplines, fetchDepartments } from '$lib/api/organization.js'; import { fetchDisciplines, fetchDepartments } from '$lib/api/organization.js';
import { fetchSpecimenTypes } from '$lib/api/specimens.js';
import { success as toastSuccess, error as toastError } from '$lib/utils/toast.js'; import { success as toastSuccess, error as toastError } from '$lib/utils/toast.js';
import DataTable from '$lib/components/DataTable.svelte'; import DataTable from '$lib/components/DataTable.svelte';
import Modal from '$lib/components/Modal.svelte'; import Modal from '$lib/components/Modal.svelte';
@ -14,7 +13,6 @@
let tests = $state([]); let tests = $state([]);
let disciplines = $state([]); let disciplines = $state([]);
let departments = $state([]); let departments = $state([]);
let specimenTypes = $state([]);
let modalOpen = $state(false); let modalOpen = $state(false);
let modalMode = $state('create'); let modalMode = $state('create');
let saving = $state(false); let saving = $state(false);
@ -38,7 +36,6 @@
VisibleScr: true, VisibleScr: true,
VisibleRpt: true, VisibleRpt: true,
// Type-specific fields // Type-specific fields
SpecimenType: '',
Unit: '', Unit: '',
Formula: '', Formula: '',
// Reference ranges // Reference ranges
@ -96,10 +93,6 @@
formData.TestType === 'TEST' || formData.TestType === 'CALC' formData.TestType === 'TEST' || formData.TestType === 'CALC'
); );
const canHaveSpecimen = $derived(
formData.TestType === 'TEST' || formData.TestType === 'PARAM'
);
const canHaveFormula = $derived( const canHaveFormula = $derived(
formData.TestType === 'CALC' formData.TestType === 'CALC'
); );
@ -112,7 +105,6 @@
{ key: 'TestSiteCode', label: 'Code', class: 'font-medium' }, { key: 'TestSiteCode', label: 'Code', class: 'font-medium' },
{ key: 'TestSiteName', label: 'Name' }, { key: 'TestSiteName', label: 'Name' },
{ key: 'TestType', label: 'Type', class: 'w-32' }, { key: 'TestType', label: 'Type', class: 'w-32' },
{ key: 'SpecimenType', label: 'Specimen', class: 'w-32' },
{ key: 'Unit', label: 'Unit', class: 'w-24' }, { key: 'Unit', label: 'Unit', class: 'w-24' },
{ key: 'DisciplineName', label: 'Discipline' }, { key: 'DisciplineName', label: 'Discipline' },
{ key: 'DepartmentName', label: 'Department' }, { key: 'DepartmentName', label: 'Department' },
@ -123,8 +115,7 @@
await Promise.all([ await Promise.all([
loadTests(), loadTests(),
loadDisciplines(), loadDisciplines(),
loadDepartments(), loadDepartments()
loadSpecimenTypes()
]); ]);
}); });
@ -176,15 +167,6 @@
} }
} }
async function loadSpecimenTypes() {
try {
const response = await fetchSpecimenTypes();
specimenTypes = Array.isArray(response.data) ? response.data : [];
} catch (err) {
specimenTypes = [];
}
}
function openCreateModal() { function openCreateModal() {
modalMode = 'create'; modalMode = 'create';
activeTab = 'basic'; activeTab = 'basic';
@ -199,7 +181,6 @@
SeqRpt: '0', SeqRpt: '0',
VisibleScr: true, VisibleScr: true,
VisibleRpt: true, VisibleRpt: true,
SpecimenType: '',
Unit: '', Unit: '',
Formula: '', Formula: '',
refnum: [], refnum: [],
@ -232,7 +213,6 @@
SeqRpt: row.SeqRpt || '0', SeqRpt: row.SeqRpt || '0',
VisibleScr: row.VisibleScr === '1' || row.VisibleScr === 1 || row.VisibleScr === true, VisibleScr: row.VisibleScr === '1' || row.VisibleScr === 1 || row.VisibleScr === true,
VisibleRpt: row.VisibleRpt === '1' || row.VisibleRpt === 1 || row.VisibleRpt === true, VisibleRpt: row.VisibleRpt === '1' || row.VisibleRpt === 1 || row.VisibleRpt === true,
SpecimenType: row.SpecimenType || '',
Unit: row.Unit || '', Unit: row.Unit || '',
Formula: row.Formula || '', Formula: row.Formula || '',
refnum: row.refnum || [], refnum: row.refnum || [],
@ -364,9 +344,6 @@
const payload = { ...formData }; const payload = { ...formData };
// Remove fields not applicable to this type // Remove fields not applicable to this type
if (!canHaveSpecimen) {
delete payload.SpecimenType;
}
if (!canHaveUnit) { if (!canHaveUnit) {
delete payload.Unit; delete payload.Unit;
} }
@ -447,12 +424,6 @@
filteredDepartments.map(d => ({ value: d.DepartmentID, label: d.DepartmentName })) filteredDepartments.map(d => ({ value: d.DepartmentID, label: d.DepartmentName }))
); );
const specimenTypeOptions = $derived(
specimenTypes.map(s => ({
value: s.SpecimenCode || s.SpecimenType,
label: s.SpecimenName || s.SpecimenType
}))
);
</script> </script>
<div class="p-6"> <div class="p-6">
@ -649,31 +620,7 @@
</div> </div>
<!-- Type-specific fields --> <!-- Type-specific fields -->
{#if canHaveSpecimen}
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<SelectDropdown
label="Specimen Type"
name="specimenType"
bind:value={formData.SpecimenType}
options={specimenTypeOptions}
placeholder="Select specimen type..."
/>
{#if canHaveUnit} {#if canHaveUnit}
<div class="form-control">
<label class="label" for="unit">
<span class="label-text font-medium">Unit</span>
</label>
<input
id="unit"
type="text"
class="input input-bordered w-full"
bind:value={formData.Unit}
placeholder="e.g., mg/dL"
/>
</div>
{/if}
</div>
{:else if canHaveUnit}
<div class="grid grid-cols-1 md:grid-cols-2 gap-4"> <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
{#if canHaveFormula} {#if canHaveFormula}
<div class="form-control"> <div class="form-control">