From b36e577f88b702b8ca78adf5a7236327134dc82f Mon Sep 17 00:00:00 2001 From: Narul Hidayah Date: Thu, 18 Jun 2026 00:50:21 +0900 Subject: [PATCH] reporting --- .../reporting/emergency_diagnosis_fact.ts | 54 +++++++++++++++ src/entity/reporting/emergency_fact.ts | 64 +++++++++++++++++ .../reporting/emergency_outcome_fact.ts | 52 ++++++++++++++ .../reporting/emergency_referral_name_fact.ts | 60 ++++++++++++++++ .../emergency_referral_source_fact.ts | 46 +++++++++++++ src/entity/reporting/opd_clinic_map.ts | 42 ++++++++++++ src/entity/reporting/opd_cron_state.ts | 25 +++++++ src/entity/reporting/opd_diagnosis_fact.ts | 62 +++++++++++++++++ src/entity/reporting/opd_referral_fact.ts | 59 ++++++++++++++++ src/entity/reporting/opd_visit_fact.ts | 68 +++++++++++++++++++ src/index.ts | 3 +- src/schema/reporting.ts | 11 +++ src/types/opd_report_grain.ts | 6 ++ 13 files changed, 551 insertions(+), 1 deletion(-) create mode 100644 src/entity/reporting/emergency_diagnosis_fact.ts create mode 100644 src/entity/reporting/emergency_fact.ts create mode 100644 src/entity/reporting/emergency_outcome_fact.ts create mode 100644 src/entity/reporting/emergency_referral_name_fact.ts create mode 100644 src/entity/reporting/emergency_referral_source_fact.ts create mode 100644 src/entity/reporting/opd_clinic_map.ts create mode 100644 src/entity/reporting/opd_cron_state.ts create mode 100644 src/entity/reporting/opd_diagnosis_fact.ts create mode 100644 src/entity/reporting/opd_referral_fact.ts create mode 100644 src/entity/reporting/opd_visit_fact.ts create mode 100644 src/schema/reporting.ts create mode 100644 src/types/opd_report_grain.ts diff --git a/src/entity/reporting/emergency_diagnosis_fact.ts b/src/entity/reporting/emergency_diagnosis_fact.ts new file mode 100644 index 0000000..440c93f --- /dev/null +++ b/src/entity/reporting/emergency_diagnosis_fact.ts @@ -0,0 +1,54 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + Index, +} from "typeorm"; +import { OpdReportGrain } from "../../types/opd_report_grain"; + +@Entity({ schema: "reporting", name: "emergency_diagnosis_fact" }) +@Index(["grain", "period_start", "period_end", "rank", "is_new_only"], { + unique: true, +}) +export class EmergencyDiagnosisFact { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ + type: "enum", + enum: OpdReportGrain, + nullable: false, + }) + grain: OpdReportGrain; + + @Column({ type: "date", nullable: false }) + period_start: string; + + @Column({ type: "date", nullable: false }) + period_end: string; + + @Column({ nullable: true, length: 64 }) + icd_code: string | null; + + @Column({ nullable: false, length: 512 }) + diagnosis_name: string; + + @Column({ type: "int", nullable: false, default: 0 }) + total_visits: number; + + @Column({ type: "int", nullable: false, default: 0 }) + rank: number; + + @Column({ type: "boolean", nullable: false, default: false }) + is_new_only: boolean; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; +} \ No newline at end of file diff --git a/src/entity/reporting/emergency_fact.ts b/src/entity/reporting/emergency_fact.ts new file mode 100644 index 0000000..f5b1aaa --- /dev/null +++ b/src/entity/reporting/emergency_fact.ts @@ -0,0 +1,64 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + Index, +} from "typeorm"; +import { OpdReportGrain } from "../../types/opd_report_grain"; + +@Entity({ schema: "reporting", name: "emergency_fact" }) +@Index(["grain", "period_start", "period_end"], { unique: true }) +export class EmergencyFact { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ + type: "enum", + enum: OpdReportGrain, + nullable: false, + }) + grain: OpdReportGrain; + + @Column({ type: "date", nullable: false }) + period_start: string; + + @Column({ type: "date", nullable: false }) + period_end: string; + + @Column({ type: "int", nullable: false, default: 0 }) + total_patients: number; + + @Column({ type: "int", nullable: false, default: 0 }) + new_patients_male: number; + + @Column({ type: "int", nullable: false, default: 0 }) + new_patients_female: number; + + @Column({ type: "int", nullable: false, default: 0 }) + returning_patients_male: number; + + @Column({ type: "int", nullable: false, default: 0 }) + returning_patients_female: number; + + @Column({ type: "int", nullable: false, default: 0 }) + foreign_patients_male: number; + + @Column({ type: "int", nullable: false, default: 0 }) + foreign_patients_female: number; + + @Column({ type: "int", nullable: false, default: 0 }) + total_referral_male: number; + + @Column({ type: "int", nullable: false, default: 0 }) + total_referral_female: number; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; +} \ No newline at end of file diff --git a/src/entity/reporting/emergency_outcome_fact.ts b/src/entity/reporting/emergency_outcome_fact.ts new file mode 100644 index 0000000..fd829b5 --- /dev/null +++ b/src/entity/reporting/emergency_outcome_fact.ts @@ -0,0 +1,52 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + Index, +} from "typeorm"; +import { OpdReportGrain } from "../../types/opd_report_grain"; + +@Entity({ schema: "reporting", name: "emergency_outcome_fact" }) +@Index(["grain", "period_start", "period_end"], { unique: true }) +export class EmergencyOutcomeFact { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ + type: "enum", + enum: OpdReportGrain, + nullable: false, + }) + grain: OpdReportGrain; + + @Column({ type: "date", nullable: false }) + period_start: string; + + @Column({ type: "date", nullable: false }) + period_end: string; + + @Column({ type: "int", nullable: false, default: 0 }) + observation: number; + + @Column({ type: "int", nullable: false, default: 0 }) + admitted: number; + + @Column({ type: "int", nullable: false, default: 0 }) + discharged: number; + + @Column({ type: "int", nullable: false, default: 0 }) + dead: number; + + @Column({ type: "int", nullable: false, default: 0 }) + dba: number; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; +} \ No newline at end of file diff --git a/src/entity/reporting/emergency_referral_name_fact.ts b/src/entity/reporting/emergency_referral_name_fact.ts new file mode 100644 index 0000000..58cbc54 --- /dev/null +++ b/src/entity/reporting/emergency_referral_name_fact.ts @@ -0,0 +1,60 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + Index, +} from "typeorm"; +import { OpdReportGrain } from "../../types/opd_report_grain"; + +export enum EmergencyReferralType { + HOSPITAL = "hospital", + HEALTH_CENTER = "health_center", +} + +@Entity({ schema: "reporting", name: "emergency_referral_name_fact" }) +@Index(["grain", "period_start", "period_end", "referral_type", "rank"], { + unique: true, +}) +export class EmergencyReferralNameFact { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ + type: "enum", + enum: OpdReportGrain, + nullable: false, + }) + grain: OpdReportGrain; + + @Column({ type: "date", nullable: false }) + period_start: string; + + @Column({ type: "date", nullable: false }) + period_end: string; + + @Column({ + type: "enum", + enum: EmergencyReferralType, + nullable: false, + }) + referral_type: EmergencyReferralType; + + @Column({ nullable: false, length: 512 }) + referral_name: string; + + @Column({ type: "int", nullable: false, default: 0 }) + total_patients: number; + + @Column({ type: "int", nullable: false, default: 0 }) + rank: number; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; +} \ No newline at end of file diff --git a/src/entity/reporting/emergency_referral_source_fact.ts b/src/entity/reporting/emergency_referral_source_fact.ts new file mode 100644 index 0000000..33b1d03 --- /dev/null +++ b/src/entity/reporting/emergency_referral_source_fact.ts @@ -0,0 +1,46 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + Index, +} from "typeorm"; +import { OpdReportGrain } from "../../types/opd_report_grain"; + +@Entity({ schema: "reporting", name: "emergency_referral_source_fact" }) +@Index(["grain", "period_start", "period_end"], { unique: true }) +export class EmergencyReferralSourceFact { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ + type: "enum", + enum: OpdReportGrain, + nullable: false, + }) + grain: OpdReportGrain; + + @Column({ type: "date", nullable: false }) + period_start: string; + + @Column({ type: "date", nullable: false }) + period_end: string; + + @Column({ type: "int", nullable: false, default: 0 }) + direct: number; + + @Column({ type: "int", nullable: false, default: 0 }) + hospital_referral: number; + + @Column({ type: "int", nullable: false, default: 0 }) + health_center_referral: number; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; +} \ No newline at end of file diff --git a/src/entity/reporting/opd_clinic_map.ts b/src/entity/reporting/opd_clinic_map.ts new file mode 100644 index 0000000..db46e32 --- /dev/null +++ b/src/entity/reporting/opd_clinic_map.ts @@ -0,0 +1,42 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToOne, + JoinColumn, + Index, +} from "typeorm"; +import { Room } from "../room"; + +@Entity({ schema: "reporting", name: "opd_clinic_map" }) +@Index(["report_name"], { unique: true }) +export class OpdClinicMap { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ nullable: false, length: 256 }) + report_name: string; + + @Column({ nullable: true, length: 256 }) + parent_report_name: string | null; + + @ManyToOne(() => Room, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn({ name: "room_id" }) + room: Room | null; + + @Column({ type: "smallint", nullable: false, default: 0 }) + sort_order: number; + + @Column({ type: "boolean", nullable: false, default: true }) + is_active: boolean; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; +} diff --git a/src/entity/reporting/opd_cron_state.ts b/src/entity/reporting/opd_cron_state.ts new file mode 100644 index 0000000..b1aae8a --- /dev/null +++ b/src/entity/reporting/opd_cron_state.ts @@ -0,0 +1,25 @@ +import { + Entity, + PrimaryColumn, + Column, + UpdateDateColumn, +} from "typeorm"; + +@Entity({ schema: "reporting", name: "opd_cron_state" }) +export class OpdCronState { + @PrimaryColumn({ length: 128 }) + job_name: string; + + @Column({ type: "timestamptz", nullable: true }) + last_success_at: Date | null; + + @Column({ type: "date", nullable: true }) + last_period_end: string | null; + + @Column({ type: "text", nullable: true }) + last_error: string | null; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; +} diff --git a/src/entity/reporting/opd_diagnosis_fact.ts b/src/entity/reporting/opd_diagnosis_fact.ts new file mode 100644 index 0000000..369f7b3 --- /dev/null +++ b/src/entity/reporting/opd_diagnosis_fact.ts @@ -0,0 +1,62 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToOne, + JoinColumn, + Index, +} from "typeorm"; +import { Room } from "../room"; +import { OpdReportGrain } from "../../types/opd_report_grain"; + +@Entity({ schema: "reporting", name: "opd_diagnosis_fact" }) +@Index(["grain", "period_start", "period_end", "rank", "is_new_only", "report_name"], { unique: true }) +export class OpdDiagnosisFact { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ + type: "enum", + enum: OpdReportGrain, + nullable: false, + }) + grain: OpdReportGrain; + + @Column({ type: "date", nullable: false }) + period_start: string; + + @Column({ type: "date", nullable: false }) + period_end: string; + + @ManyToOne(() => Room, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn({ name: "room_id" }) + room: Room | null; + + @Column({ nullable: true, length: 256 }) + report_name: string | null; + + @Column({ type: "smallint", nullable: false }) + rank: number; + + @Column({ nullable: true, length: 32 }) + icd_code: string | null; + + @Column({ nullable: false, length: 512 }) + diagnosis_name: string; + + @Column({ type: "int", nullable: false, default: 0 }) + total_visits: number; + + @Column({ type: "boolean", nullable: false, default: false }) + is_new_only: boolean; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; +} diff --git a/src/entity/reporting/opd_referral_fact.ts b/src/entity/reporting/opd_referral_fact.ts new file mode 100644 index 0000000..1eb2254 --- /dev/null +++ b/src/entity/reporting/opd_referral_fact.ts @@ -0,0 +1,59 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToOne, + JoinColumn, + Index, +} from "typeorm"; +import { Room } from "../room"; +import { OpdReportGrain } from "../../types/opd_report_grain"; + +@Entity({ schema: "reporting", name: "opd_referral_fact" }) +@Index(["grain", "period_start", "period_end", "report_name"], { unique: true }) +export class OpdReferralFact { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ + type: "enum", + enum: OpdReportGrain, + nullable: false, + }) + grain: OpdReportGrain; + + @Column({ type: "date", nullable: false }) + period_start: string; + + @Column({ type: "date", nullable: false }) + period_end: string; + + @ManyToOne(() => Room, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn({ name: "room_id" }) + room: Room | null; + + @Column({ nullable: true, length: 256 }) + report_name: string | null; + + @Column({ type: "int", nullable: false, default: 0 }) + hospital_referral: number; + + @Column({ type: "int", nullable: false, default: 0 }) + centro_saude_referral: number; + + @Column({ type: "int", nullable: false, default: 0 }) + internal_referral: number; + + @Column({ type: "int", nullable: false, default: 0 }) + no_referral: number; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; +} diff --git a/src/entity/reporting/opd_visit_fact.ts b/src/entity/reporting/opd_visit_fact.ts new file mode 100644 index 0000000..20457fc --- /dev/null +++ b/src/entity/reporting/opd_visit_fact.ts @@ -0,0 +1,68 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToOne, + JoinColumn, + Index, +} from "typeorm"; +import { Room } from "../room"; +import { OpdReportGrain } from "../../types/opd_report_grain"; + +@Entity({ schema: "reporting", name: "opd_visit_fact" }) +@Index(["grain", "period_start", "period_end", "report_name"], { unique: true }) +export class OpdVisitFact { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ + type: "enum", + enum: OpdReportGrain, + nullable: false, + }) + grain: OpdReportGrain; + + @Column({ type: "date", nullable: false }) + period_start: string; + + @Column({ type: "date", nullable: false }) + period_end: string; + + @ManyToOne(() => Room, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn({ name: "room_id" }) + room: Room | null; + + @Column({ nullable: false, length: 256 }) + report_name: string; + + @Column({ type: "int", nullable: false, default: 0 }) + total_visits: number; + + @Column({ type: "int", nullable: false, default: 0 }) + new_visits: number; + + @Column({ type: "int", nullable: false, default: 0 }) + existing_visits: number; + + @Column({ type: "int", nullable: false, default: 0 }) + foreigner_visits: number; + + @Column({ type: "int", nullable: false, default: 0 }) + male_visits: number; + + @Column({ type: "int", nullable: false, default: 0 }) + female_visits: number; + + @Column({ type: "int", nullable: true }) + referral_total: number | null; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; +} diff --git a/src/index.ts b/src/index.ts index 521db76..017cebb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,4 +7,5 @@ export * from "./schema/pharmacy"; export * from "./schema/pharmacy_logistic"; export * from "./schema/cashier"; export * from "./schema/blood_bank"; -export * from "./schema/card_management"; \ No newline at end of file +export * from "./schema/card_management"; +export * from "./schema/reporting"; \ No newline at end of file diff --git a/src/schema/reporting.ts b/src/schema/reporting.ts new file mode 100644 index 0000000..30e7813 --- /dev/null +++ b/src/schema/reporting.ts @@ -0,0 +1,11 @@ +export * from "../types/opd_report_grain"; +export * from "../entity/reporting/opd_clinic_map"; +export * from "../entity/reporting/opd_visit_fact"; +export * from "../entity/reporting/opd_diagnosis_fact"; +export * from "../entity/reporting/opd_referral_fact"; +export * from "../entity/reporting/opd_cron_state"; +export * from "../entity/reporting/emergency_fact"; +export * from "../entity/reporting/emergency_outcome_fact"; +export * from "../entity/reporting/emergency_referral_source_fact"; +export * from "../entity/reporting/emergency_referral_name_fact"; +export * from "../entity/reporting/emergency_diagnosis_fact"; diff --git a/src/types/opd_report_grain.ts b/src/types/opd_report_grain.ts new file mode 100644 index 0000000..7dd2558 --- /dev/null +++ b/src/types/opd_report_grain.ts @@ -0,0 +1,6 @@ +export enum OpdReportGrain { + DAY = "day", + MONTH = "month", + QUARTER = "quarter", + YEAR = "year", +}