Files
temetro/backend/src/db/schema/dispenses.ts
T
Khalid Abdi f0fe501d62 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>
2026-06-16 20:44:47 +03:00

36 lines
1.6 KiB
TypeScript

import { index, integer, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { organization, user } from "./auth.js";
// One row per dispensing event — the record of a medication actually handed to a
// patient at the pharmacy, scoped to a clinic (organization). Distinct from
// `prescriptions` (the order) and `inventory` (standing stock): this is the
// fulfilment ledger ("who took which medication"). Patient + dispenser identity
// are denormalized so the list renders without joining; `prescriptionId` links
// back to the source order when the dispense came from the queue.
export const dispenses = pgTable(
"dispenses",
{
id: uuid("id").primaryKey().defaultRandom(),
organizationId: text("organization_id")
.notNull()
.references(() => organization.id, { onDelete: "cascade" }),
patientFileNumber: text("patient_file_number").notNull().default(""),
patientName: text("patient_name").notNull(),
patientInitials: text("patient_initials").notNull().default(""),
medication: text("medication").notNull(),
dose: text("dose").notNull().default(""),
quantity: integer("quantity").notNull().default(0),
unit: text("unit").notNull().default(""),
prescriptionId: uuid("prescription_id"),
dispensedBy: text("dispensed_by").references(() => user.id, {
onDelete: "set null",
}),
dispensedByName: text("dispensed_by_name").notNull().default(""),
dispensedAt: timestamp("dispensed_at").defaultNow().notNull(),
notes: text("notes"),
createdAt: timestamp("created_at").defaultNow().notNull(),
},
(t) => [index("dispenses_org_idx").on(t.organizationId)],
);