diff --git a/messages/it.json b/messages/it.json index b0b95afe3..34115c96c 100644 --- a/messages/it.json +++ b/messages/it.json @@ -2066,7 +2066,7 @@ "logInjectionSiteConfirm": "Salva il sito", "logInjectionSiteNoneAvailable": "Nessun sito di iniezione disponibile: tutti i siti sono esclusi nelle tue impostazioni.", "logInjectionSiteSaveFailed": "Impossibile salvare il sito di iniezione. Riprova.", - "perSlotUnits": "{units} per dose", + "perSlotUnits": "{units} per singola dose", "trackInjectionSitesToggle": "Registra i siti di iniezione", "trackInjectionSitesHint": "Dopo l'assunzione di una dose, chiedi quale sito è stato usato e suggerisci la rotazione successiva.", "allowedSitesLabel": "Siti consentiti", diff --git a/src/lib/medications/inventory/__tests__/consumption.test.ts b/src/lib/medications/inventory/__tests__/consumption.test.ts index 7928e09e9..bf31aff0d 100644 --- a/src/lib/medications/inventory/__tests__/consumption.test.ts +++ b/src/lib/medications/inventory/__tests__/consumption.test.ts @@ -32,12 +32,20 @@ interface FakeEvent { id: string; userId: string; medicationId: string; + scheduledFor: Date; takenAt: Date | null; skipped: boolean; deletedAt: Date | null; inventoryConsumption: unknown; } +/** #219 — a schedule row the per-slot units resolver reads. */ +interface FakeSchedule { + timesOfDay: string[]; + windowStart: string; + unitsPerDose: number | null; +} + interface FakeItem { id: string; userId: string; @@ -57,6 +65,10 @@ interface FakeState { events: FakeEvent[]; items: FakeItem[]; unitsPerDose: number; + // #219 — per-slot resolver inputs. Default to no schedules + UTC so every + // pre-existing scenario inherits the medication-level `unitsPerDose`. + schedules?: FakeSchedule[]; + timezone?: string; } type OrderSpec = Record< @@ -86,7 +98,12 @@ function sortRows(rows: FakeItem[], orderBy: OrderSpec[]): FakeItem[] { function makeClient(state: FakeState) { return { medication: { - findFirst: vi.fn(async () => ({ unitsPerDose: state.unitsPerDose })), + findFirst: vi.fn(async () => ({ + unitsPerDose: state.unitsPerDose, + // #219 — the per-slot resolver reads the user's zone + the schedules. + user: { timezone: state.timezone ?? "UTC" }, + schedules: state.schedules ?? [], + })), }, medicationIntakeEvent: { findFirst: vi.fn( @@ -95,6 +112,17 @@ function makeClient(state: FakeState) { (e) => e.id === args.where.id && e.userId === args.where.userId, ) ?? null, ), + // #219 — the import-batch path loads each event's scheduledFor anchor. + findMany: vi.fn( + async (args: { + where: { id: { in: string[] }; userId: string }; + }) => + state.events.filter( + (e) => + args.where.id.in.includes(e.id) && + e.userId === args.where.userId, + ), + ), // The hooks' atomic claim — evaluate the conditional WHERE the way // Postgres would (the gate fields plus the stamp predicate: // `Prisma.AnyNull` matches a NULL stamp, a JSON value matches by @@ -216,6 +244,7 @@ function takenEvent(overrides: Partial = {}): FakeEvent { id: "evt-1", userId: "user-1", medicationId: "med-1", + scheduledFor: NOW, takenAt: NOW, skipped: false, deletedAt: null,