From c88d5f5dfefc886d6bda370031ac9dfb54695539 Mon Sep 17 00:00:00 2001 From: Narul Hidayah Date: Thu, 11 Jun 2026 09:18:14 +0900 Subject: [PATCH 1/4] card management --- src/entity/card-management/card_inventory.ts | 74 +++++++++++++++++++ src/entity/card-management/card_stock_in.ts | 48 ++++++++++++ .../card-management/healthcare_facility.ts | 73 ++++++++++++++++++ .../card-management/running_number_log.ts | 53 +++++++++++++ src/index.ts | 3 +- src/schema/card_management.ts | 7 ++ src/types/card_inventory_status.ts | 7 ++ src/types/healthcare_facility_status.ts | 4 + src/types/healthcare_facility_type.ts | 6 ++ 9 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 src/entity/card-management/card_inventory.ts create mode 100644 src/entity/card-management/card_stock_in.ts create mode 100644 src/entity/card-management/healthcare_facility.ts create mode 100644 src/entity/card-management/running_number_log.ts create mode 100644 src/schema/card_management.ts create mode 100644 src/types/card_inventory_status.ts create mode 100644 src/types/healthcare_facility_status.ts create mode 100644 src/types/healthcare_facility_type.ts diff --git a/src/entity/card-management/card_inventory.ts b/src/entity/card-management/card_inventory.ts new file mode 100644 index 0000000..bc22ca5 --- /dev/null +++ b/src/entity/card-management/card_inventory.ts @@ -0,0 +1,74 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + DeleteDateColumn, + ManyToOne, + JoinColumn, + Index, +} from "typeorm"; +import { EmrPatient } from "../emr/emr_patient"; +import { HealthcareFacility } from "./healthcare_facility"; +import { CardInventoryStatus } from "../../types/card_inventory_status"; + +@Entity({ schema: "card_management", name: "card_inventory" }) +@Index(["card_number"], { unique: true }) +@Index(["running_number"], { unique: true }) +export class CardInventory { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => EmrPatient, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn({ name: "patientId" }) + patient: EmrPatient; + + @Column({ nullable: true, length: 64 }) + mrn: string; + + @Column({ type: "bigint", nullable: false, unique: true }) + running_number: string; + + @Column({ nullable: true, length: 64, unique: true }) + card_number: string; + + @Column({ nullable: true, length: 128 }) + tag_id: string; + + @ManyToOne(() => HealthcareFacility, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + facility: HealthcareFacility; + + @Column({ + type: "enum", + enum: CardInventoryStatus, + nullable: false, + default: CardInventoryStatus.NOT_USED, + }) + status: CardInventoryStatus; + + @Column({ type: "timestamp", nullable: true }) + printed_at: Date; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true, length: 256 }) + created_by: string; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; + + @Column({ nullable: true, length: 256 }) + updated_by: string; + + @Column({ nullable: true }) + @DeleteDateColumn() + deleted_at: Date; + + @Column({ nullable: true, length: 256 }) + deleted_by: string; +} diff --git a/src/entity/card-management/card_stock_in.ts b/src/entity/card-management/card_stock_in.ts new file mode 100644 index 0000000..c4deab9 --- /dev/null +++ b/src/entity/card-management/card_stock_in.ts @@ -0,0 +1,48 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + DeleteDateColumn, +} from "typeorm"; + +/** + * Placeholder for future batch card stock-in workflow. + * Entity only — no API, UI, or business logic yet. + */ +@Entity({ schema: "card_management", name: "card_stock_in" }) +export class CardStockIn { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ nullable: true, length: 64 }) + batch_number: string; + + @Column({ type: "int", nullable: true }) + quantity: number; + + @Column({ type: "text", nullable: true }) + notes: string; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true, length: 256 }) + created_by: string; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; + + @Column({ nullable: true, length: 256 }) + updated_by: string; + + @Column({ nullable: true }) + @DeleteDateColumn() + deleted_at: Date; + + @Column({ nullable: true, length: 256 }) + deleted_by: string; +} diff --git a/src/entity/card-management/healthcare_facility.ts b/src/entity/card-management/healthcare_facility.ts new file mode 100644 index 0000000..aec55b6 --- /dev/null +++ b/src/entity/card-management/healthcare_facility.ts @@ -0,0 +1,73 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + DeleteDateColumn, + ManyToOne, + JoinColumn, + Index, +} from "typeorm"; +import { Munisipo } from "../munisipo"; +import { Administrativu } from "../administrativu"; +import { HealthcareFacilityStatus } from "../../types/healthcare_facility_status"; +import { HealthcareFacilityType } from "../../types/healthcare_facility_type"; + +@Entity({ schema: "card_management", name: "healthcare_facility" }) +@Index(["code"], { unique: true }) +export class HealthcareFacility { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ nullable: false, length: 64, unique: true }) + code: string; + + @Column({ type: "text", nullable: false }) + name: string; + + @Column({ + type: "enum", + enum: HealthcareFacilityType, + nullable: false, + default: HealthcareFacilityType.HOSPITAL, + }) + type: HealthcareFacilityType; + + @ManyToOne(() => Munisipo, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + municipio: Munisipo; + + @ManyToOne(() => Administrativu, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + administrativu: Administrativu; + + @Column({ + type: "enum", + enum: HealthcareFacilityStatus, + nullable: false, + default: HealthcareFacilityStatus.ACTIVE, + }) + status: HealthcareFacilityStatus; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true, length: 256 }) + created_by: string; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; + + @Column({ nullable: true, length: 256 }) + updated_by: string; + + @Column({ nullable: true }) + @DeleteDateColumn() + deleted_at: Date; + + @Column({ nullable: true, length: 256 }) + deleted_by: string; +} diff --git a/src/entity/card-management/running_number_log.ts b/src/entity/card-management/running_number_log.ts new file mode 100644 index 0000000..8ec1bb5 --- /dev/null +++ b/src/entity/card-management/running_number_log.ts @@ -0,0 +1,53 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + DeleteDateColumn, + Index, +} from "typeorm"; + +@Entity({ schema: "card_management", name: "running_number_log" }) +@Index(["running_number"]) +@Index(["requested_at"]) +export class RunningNumberLog { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ type: "bigint", nullable: false }) + running_number: string; + + @Column({ nullable: false, length: 128 }) + service_name: string; + + @Column({ type: "uuid", nullable: false }) + requested_by: string; + + @Column({ nullable: false, length: 256 }) + requested_by_name: string; + + @Column({ type: "timestamp", nullable: false }) + requested_at: Date; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true, length: 256 }) + created_by: string; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; + + @Column({ nullable: true, length: 256 }) + updated_by: string; + + @Column({ nullable: true }) + @DeleteDateColumn() + deleted_at: Date; + + @Column({ nullable: true, length: 256 }) + deleted_by: string; +} diff --git a/src/index.ts b/src/index.ts index 88437b0..521db76 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,4 +6,5 @@ export * from "./schema/procurement"; export * from "./schema/pharmacy"; export * from "./schema/pharmacy_logistic"; export * from "./schema/cashier"; -export * from "./schema/blood_bank"; \ No newline at end of file +export * from "./schema/blood_bank"; +export * from "./schema/card_management"; \ No newline at end of file diff --git a/src/schema/card_management.ts b/src/schema/card_management.ts new file mode 100644 index 0000000..7823823 --- /dev/null +++ b/src/schema/card_management.ts @@ -0,0 +1,7 @@ +export * from "../types/card_inventory_status"; +export * from "../types/healthcare_facility_status"; +export * from "../types/healthcare_facility_type"; +export * from "../entity/card-management/card_inventory"; +export * from "../entity/card-management/healthcare_facility"; +export * from "../entity/card-management/running_number_log"; +export * from "../entity/card-management/card_stock_in"; diff --git a/src/types/card_inventory_status.ts b/src/types/card_inventory_status.ts new file mode 100644 index 0000000..351be3d --- /dev/null +++ b/src/types/card_inventory_status.ts @@ -0,0 +1,7 @@ +export enum CardInventoryStatus { + /** Blank card in stock — not yet assigned / injected to a patient */ + NOT_USED = "NOT_USED", + ACTIVE = "ACTIVE", + LOST = "LOST", + REPLACED = "REPLACED", +} diff --git a/src/types/healthcare_facility_status.ts b/src/types/healthcare_facility_status.ts new file mode 100644 index 0000000..5d9f5c7 --- /dev/null +++ b/src/types/healthcare_facility_status.ts @@ -0,0 +1,4 @@ +export enum HealthcareFacilityStatus { + ACTIVE = "ACTIVE", + INACTIVE = "INACTIVE", +} diff --git a/src/types/healthcare_facility_type.ts b/src/types/healthcare_facility_type.ts new file mode 100644 index 0000000..3586ff8 --- /dev/null +++ b/src/types/healthcare_facility_type.ts @@ -0,0 +1,6 @@ +export enum HealthcareFacilityType { + HOSPITAL = "HOSPITAL", + CLINIC = "CLINIC", + HEALTH_CENTER = "HEALTH_CENTER", + OTHER = "OTHER", +} From bbabd02aafa7b180528e42ce8ef192e9ecc41a8c Mon Sep 17 00:00:00 2001 From: Narul Hidayah Date: Thu, 11 Jun 2026 09:50:39 +0900 Subject: [PATCH 2/4] card management --- .../card-management/healthcare_facility.ts | 19 +------------------ src/entity/card_print_queue.ts | 12 ++++++++++++ src/schema/card_management.ts | 2 -- src/types/healthcare_facility_status.ts | 4 ---- src/types/healthcare_facility_type.ts | 6 ------ 5 files changed, 13 insertions(+), 30 deletions(-) delete mode 100644 src/types/healthcare_facility_status.ts delete mode 100644 src/types/healthcare_facility_type.ts diff --git a/src/entity/card-management/healthcare_facility.ts b/src/entity/card-management/healthcare_facility.ts index aec55b6..1b48711 100644 --- a/src/entity/card-management/healthcare_facility.ts +++ b/src/entity/card-management/healthcare_facility.ts @@ -11,9 +11,8 @@ import { } from "typeorm"; import { Munisipo } from "../munisipo"; import { Administrativu } from "../administrativu"; -import { HealthcareFacilityStatus } from "../../types/healthcare_facility_status"; -import { HealthcareFacilityType } from "../../types/healthcare_facility_type"; +/** Minimal cache — synced from external master; no local type/status enums */ @Entity({ schema: "card_management", name: "healthcare_facility" }) @Index(["code"], { unique: true }) export class HealthcareFacility { @@ -26,14 +25,6 @@ export class HealthcareFacility { @Column({ type: "text", nullable: false }) name: string; - @Column({ - type: "enum", - enum: HealthcareFacilityType, - nullable: false, - default: HealthcareFacilityType.HOSPITAL, - }) - type: HealthcareFacilityType; - @ManyToOne(() => Munisipo, { onDelete: "NO ACTION", nullable: true }) @JoinColumn() municipio: Munisipo; @@ -42,14 +33,6 @@ export class HealthcareFacility { @JoinColumn() administrativu: Administrativu; - @Column({ - type: "enum", - enum: HealthcareFacilityStatus, - nullable: false, - default: HealthcareFacilityStatus.ACTIVE, - }) - status: HealthcareFacilityStatus; - @Column() @CreateDateColumn() created_at: Date; diff --git a/src/entity/card_print_queue.ts b/src/entity/card_print_queue.ts index bb37689..b831c8e 100644 --- a/src/entity/card_print_queue.ts +++ b/src/entity/card_print_queue.ts @@ -54,6 +54,18 @@ export class CardPrintQueue { @Column({ type: "text", nullable: true }) facility_code?: string; + @Column({ type: "bigint", nullable: true }) + running_number?: string; + + @Column({ type: "text", nullable: true }) + card_number?: string; + + @Column({ type: "text", nullable: true }) + provision_job_id?: string; + + @Column({ type: "text", nullable: true }) + error_message?: string; + @Column({ type: "enum", enum: CardPrintQueueStatus, diff --git a/src/schema/card_management.ts b/src/schema/card_management.ts index 7823823..685cf55 100644 --- a/src/schema/card_management.ts +++ b/src/schema/card_management.ts @@ -1,6 +1,4 @@ export * from "../types/card_inventory_status"; -export * from "../types/healthcare_facility_status"; -export * from "../types/healthcare_facility_type"; export * from "../entity/card-management/card_inventory"; export * from "../entity/card-management/healthcare_facility"; export * from "../entity/card-management/running_number_log"; diff --git a/src/types/healthcare_facility_status.ts b/src/types/healthcare_facility_status.ts deleted file mode 100644 index 5d9f5c7..0000000 --- a/src/types/healthcare_facility_status.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum HealthcareFacilityStatus { - ACTIVE = "ACTIVE", - INACTIVE = "INACTIVE", -} diff --git a/src/types/healthcare_facility_type.ts b/src/types/healthcare_facility_type.ts deleted file mode 100644 index 3586ff8..0000000 --- a/src/types/healthcare_facility_type.ts +++ /dev/null @@ -1,6 +0,0 @@ -export enum HealthcareFacilityType { - HOSPITAL = "HOSPITAL", - CLINIC = "CLINIC", - HEALTH_CENTER = "HEALTH_CENTER", - OTHER = "OTHER", -} From 7145d34dabe12646231e84169c9c5603f7ea3518 Mon Sep 17 00:00:00 2001 From: Narul Hidayah Date: Thu, 11 Jun 2026 10:14:22 +0900 Subject: [PATCH 3/4] upd --- src/entity/card-management/card_inventory.ts | 6 +- .../card-management/healthcare_facility.ts | 56 ------------------- src/schema/card_management.ts | 1 - 3 files changed, 2 insertions(+), 61 deletions(-) delete mode 100644 src/entity/card-management/healthcare_facility.ts diff --git a/src/entity/card-management/card_inventory.ts b/src/entity/card-management/card_inventory.ts index bc22ca5..d599f71 100644 --- a/src/entity/card-management/card_inventory.ts +++ b/src/entity/card-management/card_inventory.ts @@ -10,7 +10,6 @@ import { Index, } from "typeorm"; import { EmrPatient } from "../emr/emr_patient"; -import { HealthcareFacility } from "./healthcare_facility"; import { CardInventoryStatus } from "../../types/card_inventory_status"; @Entity({ schema: "card_management", name: "card_inventory" }) @@ -36,9 +35,8 @@ export class CardInventory { @Column({ nullable: true, length: 128 }) tag_id: string; - @ManyToOne(() => HealthcareFacility, { onDelete: "NO ACTION", nullable: true }) - @JoinColumn() - facility: HealthcareFacility; + @Column({ nullable: true, length: 64 }) + facility_code: string; @Column({ type: "enum", diff --git a/src/entity/card-management/healthcare_facility.ts b/src/entity/card-management/healthcare_facility.ts deleted file mode 100644 index 1b48711..0000000 --- a/src/entity/card-management/healthcare_facility.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - CreateDateColumn, - UpdateDateColumn, - DeleteDateColumn, - ManyToOne, - JoinColumn, - Index, -} from "typeorm"; -import { Munisipo } from "../munisipo"; -import { Administrativu } from "../administrativu"; - -/** Minimal cache — synced from external master; no local type/status enums */ -@Entity({ schema: "card_management", name: "healthcare_facility" }) -@Index(["code"], { unique: true }) -export class HealthcareFacility { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column({ nullable: false, length: 64, unique: true }) - code: string; - - @Column({ type: "text", nullable: false }) - name: string; - - @ManyToOne(() => Munisipo, { onDelete: "NO ACTION", nullable: true }) - @JoinColumn() - municipio: Munisipo; - - @ManyToOne(() => Administrativu, { onDelete: "NO ACTION", nullable: true }) - @JoinColumn() - administrativu: Administrativu; - - @Column() - @CreateDateColumn() - created_at: Date; - - @Column({ nullable: true, length: 256 }) - created_by: string; - - @Column({ nullable: true }) - @UpdateDateColumn() - updated_at: Date; - - @Column({ nullable: true, length: 256 }) - updated_by: string; - - @Column({ nullable: true }) - @DeleteDateColumn() - deleted_at: Date; - - @Column({ nullable: true, length: 256 }) - deleted_by: string; -} diff --git a/src/schema/card_management.ts b/src/schema/card_management.ts index 685cf55..82a1a99 100644 --- a/src/schema/card_management.ts +++ b/src/schema/card_management.ts @@ -1,5 +1,4 @@ export * from "../types/card_inventory_status"; export * from "../entity/card-management/card_inventory"; -export * from "../entity/card-management/healthcare_facility"; export * from "../entity/card-management/running_number_log"; export * from "../entity/card-management/card_stock_in"; From 983df32df4597043fb8bf7c65d643260db6d4b21 Mon Sep 17 00:00:00 2001 From: Iki Date: Thu, 11 Jun 2026 12:04:50 +0900 Subject: [PATCH 4/4] feat: add emr_observation_record --- src/entity/emr/emr_observation_record.ts | 82 ++++++++++++++++++++++++ src/enum/avpu.ts | 6 ++ src/schema/emr.ts | 2 + 3 files changed, 90 insertions(+) create mode 100644 src/entity/emr/emr_observation_record.ts create mode 100644 src/enum/avpu.ts diff --git a/src/entity/emr/emr_observation_record.ts b/src/entity/emr/emr_observation_record.ts new file mode 100644 index 0000000..09c40c7 --- /dev/null +++ b/src/entity/emr/emr_observation_record.ts @@ -0,0 +1,82 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + DeleteDateColumn, + ManyToOne, + JoinColumn, + Index, +} from "typeorm"; + +import { Avpu } from "../../enum/avpu"; +import { User } from "../users"; +import { EmrRegistration } from "./emr_registration"; + +@Entity("emr_observation_record", { schema: "emr" }) +@Index("idx_emr_observation_record_registration", ["registration"]) +export class ObservationRecord { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => EmrRegistration, { onDelete: "CASCADE" }) + @JoinColumn({ name: "registration_id" }) + registration: EmrRegistration; + + @Column({ length: 5 }) + oras: string; + + @Column({ nullable: true, type: "int2" }) + respirasi: number | null; + + @Column({ nullable: true, type: "int2" }) + spo2: number | null; + + @Column({ nullable: true, type: "int2" }) + hr: number | null; + + @Column({ nullable: true, type: "int2" }) + bp_systolic: number | null; + + @Column({ nullable: true, type: "int2" }) + bp_diastolic: number | null; + + @Column({ nullable: true, type: "float" }) + temperatura: number | null; + + @Column({ + type: "enum", + enum: Avpu, + nullable: true, + }) + avpu: Avpu | null; + + @Column({ nullable: true, type: "float" }) + todan: number | null; + + @ManyToOne(() => User, { onDelete: "NO ACTION" }) + @JoinColumn({ name: "assina_uuid" }) + assina: User; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true, length: 256 }) + created_by: string; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; + + @Column({ nullable: true, length: 256 }) + updated_by: string; + + @Column({ nullable: true }) + @DeleteDateColumn() + deleted_at: Date; + + @Column({ nullable: true, length: 256 }) + deleted_by: string; +} diff --git a/src/enum/avpu.ts b/src/enum/avpu.ts new file mode 100644 index 0000000..e608282 --- /dev/null +++ b/src/enum/avpu.ts @@ -0,0 +1,6 @@ +export enum Avpu { + A = "A", + V = "V", + P = "P", + U = "U", +} diff --git a/src/schema/emr.ts b/src/schema/emr.ts index 7eefeb1..a741bab 100644 --- a/src/schema/emr.ts +++ b/src/schema/emr.ts @@ -55,6 +55,7 @@ export * from "../entity/treatment/treatment_plan"; export * from "../entity/treatment/treatment_plan_session"; export * from "../entity/emr/emr_registration_treatment"; export * from "../entity/emr/emr_ancillary_service_order"; +export * from "../entity/emr/emr_observation_record"; export * from "../types/registration_type"; export * from "../types/registration_status"; @@ -63,6 +64,7 @@ export * from "../types/prescription_pharmacy_status"; export * from "../types/radiology_order_status"; export * from "../types/laboratory_order_status"; export * from "../enum/consciousness"; +export * from "../enum/avpu"; export * from "../types/patient_category"; export * from "../types/citizen"; export * from "../types/treatment_session";