Files
temetro/backend/src/lib/inventory-validation.ts
T
Khalid Abdi 67fdf15de4 backend: org-scoped pharmacy inventory model
Add an `inventory` resource mirroring the prescriptions feature end-to-end:
Drizzle table (org-scoped, indexed), domain type, zod validation, service
(list/get/create/update/delete), and an RBAC-gated CRUD router mounted at
/api/inventory. Grant the new `inventory` statement to roles — pharmacy gets
read/write, full clinicians read/write/delete, reception/lab none — in both the
backend access control and (mirrored) the frontend. Record writes in the
activity log via a new `inventory` entity type. Includes the migration and an
idempotent demo seed script.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 19:16:28 +03:00

24 lines
899 B
TypeScript

import { z } from "zod";
const nonEmpty = z.string().trim().min(1);
// Payload accepted by POST/PUT /api/inventory. Only the medication name is
// required; quantities default to 0 and the descriptive fields to empty strings
// so a quick add (name only) is valid.
export const inventoryInputSchema = z.object({
name: nonEmpty.max(200),
form: z.string().trim().max(120).default(""),
strength: z.string().trim().max(120).default(""),
unit: z.string().trim().max(60).default(""),
stockQuantity: z.number().int().min(0).max(1_000_000).default(0),
reorderThreshold: z.number().int().min(0).max(1_000_000).default(0),
location: z.string().trim().max(200).default(""),
expiresAt: z
.string()
.regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be YYYY-MM-DD.")
.nullish(),
notes: z.string().max(5000).nullish(),
});
export type InventoryInput = z.infer<typeof inventoryInputSchema>;