mirror of
https://github.com/temetro/temetro.git
synced 2026-08-12 03:26:53 +00:00
backend: prescription start/end dates + dispense ledger
Add optional startDate/endDate columns to prescriptions (schema, validation, types, service) — when set, endDate drives expiry. Add a new append-only `dispenses` resource (schema, types, validation, service, route at /api/dispenses) recording who received which medication, gated on the existing inventory RBAC statement. Migration 0020. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { desc, eq } from "drizzle-orm";
|
||||
|
||||
import { db } from "../db/index.js";
|
||||
import { dispenses } from "../db/schema/dispenses.js";
|
||||
import type { DispenseInput } from "../lib/dispense-validation.js";
|
||||
import type { Dispense } from "../types/dispense.js";
|
||||
|
||||
type DispenseRow = typeof dispenses.$inferSelect;
|
||||
|
||||
function toDispense(row: DispenseRow): Dispense {
|
||||
return {
|
||||
id: row.id,
|
||||
fileNumber: row.patientFileNumber,
|
||||
name: row.patientName,
|
||||
initials: row.patientInitials,
|
||||
medication: row.medication,
|
||||
dose: row.dose,
|
||||
quantity: row.quantity,
|
||||
unit: row.unit,
|
||||
prescriptionId: row.prescriptionId,
|
||||
dispensedBy: row.dispensedBy,
|
||||
dispensedByName: row.dispensedByName,
|
||||
dispensedAt: row.dispensedAt.toISOString(),
|
||||
notes: row.notes,
|
||||
createdAt: row.createdAt.toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function listDispenses(orgId: string): Promise<Dispense[]> {
|
||||
const rows = await db
|
||||
.select()
|
||||
.from(dispenses)
|
||||
.where(eq(dispenses.organizationId, orgId))
|
||||
.orderBy(desc(dispenses.dispensedAt));
|
||||
return rows.map(toDispense);
|
||||
}
|
||||
|
||||
export async function createDispense(
|
||||
orgId: string,
|
||||
dispenser: { id: string; name: string },
|
||||
input: DispenseInput,
|
||||
): Promise<Dispense> {
|
||||
const [row] = await db
|
||||
.insert(dispenses)
|
||||
.values({
|
||||
organizationId: orgId,
|
||||
patientFileNumber: input.fileNumber,
|
||||
patientName: input.name,
|
||||
patientInitials: input.initials,
|
||||
medication: input.medication,
|
||||
dose: input.dose,
|
||||
quantity: input.quantity,
|
||||
unit: input.unit,
|
||||
prescriptionId: input.prescriptionId ?? null,
|
||||
dispensedBy: dispenser.id,
|
||||
dispensedByName: dispenser.name,
|
||||
notes: input.notes ?? null,
|
||||
})
|
||||
.returning();
|
||||
return toDispense(row!);
|
||||
}
|
||||
@@ -22,6 +22,8 @@ function toPrescription(row: PrescriptionRow): Prescription {
|
||||
frequency: row.frequency,
|
||||
prescriber: row.prescriber,
|
||||
prescribedAt: row.prescribedAt,
|
||||
startDate: row.startDate,
|
||||
endDate: row.endDate,
|
||||
status: row.status,
|
||||
duration: row.duration,
|
||||
notes: row.notes,
|
||||
@@ -45,6 +47,8 @@ function columns(orgId: string, input: PrescriptionInput, createdBy?: string) {
|
||||
duration: input.duration ?? null,
|
||||
notes: input.notes ?? null,
|
||||
source: input.source,
|
||||
startDate: input.startDate ?? null,
|
||||
endDate: input.endDate ?? null,
|
||||
// Only set prescribedAt when supplied; otherwise the column default (today).
|
||||
...(input.prescribedAt ? { prescribedAt: input.prescribedAt } : {}),
|
||||
...(createdBy ? { createdBy } : {}),
|
||||
|
||||
Reference in New Issue
Block a user