pelagia-portal/App/lib/po-activity.ts
Claude (auto-fix) 3335977773
All checks were successful
PR checks / checks (pull_request) Successful in 53s
PR checks / integration (pull_request) Successful in 31s
feat(activity): show partial payment amount in PO timeline
The PO Activity timeline rendered every partial payment as the generic
"Partial payment confirmed". markPaid() already persists the instalment
amount on the PARTIAL_PAYMENT_CONFIRMED action's metadata
(metadata.paymentAmount), so surface it: the row now reads
"Partial payment of <amount> confirmed" using the PO's own currency.

Falls back to the plain label when paymentAmount is missing or
non-numeric (older audit rows) so historical POs never render NaN.

Extracted ACTION_LABELS + the new actionLabel() helper into
lib/po-activity.ts so the label logic is unit-testable without pulling
the server-only PoDetail component (and its storage/auth imports) into
jsdom.

Fixes #140
2026-06-28 00:24:28 +05:30

40 lines
1.6 KiB
TypeScript

import type { Prisma } from "@prisma/client";
import { formatCurrency } from "@/lib/utils";
// Human-readable labels for each POAction type, shown in the PO Activity timeline.
export const ACTION_LABELS: Record<string, string> = {
CREATED: "Created",
SUBMITTED: "Submitted for review",
APPROVED: "Approved",
APPROVED_WITH_NOTE: "Approved with note",
REJECTED: "Rejected",
EDITS_REQUESTED: "Edits requested",
VENDOR_ID_REQUESTED: "Vendor ID requested",
VENDOR_ID_PROVIDED: "Vendor ID provided",
PAYMENT_SENT: "Payment confirmed",
PARTIAL_PAYMENT_CONFIRMED: "Partial payment confirmed",
RECEIPT_CONFIRMED: "Receipt confirmed",
PARTIAL_RECEIPT_CONFIRMED: "Partial receipt confirmed",
CLOSED: "Closed",
MANAGER_LINE_EDIT: "Manager amended line items",
PRODUCT_PRICE_UPDATED: "Product prices updated",
CANCELLED: "Cancelled",
SUPERSEDED: "Superseded",
};
// Produce the Activity-timeline label for an action. Most actions use the static
// ACTION_LABELS map; PARTIAL_PAYMENT_CONFIRMED interpolates the instalment amount
// from the action's metadata (already persisted by markPaid) — issue #140.
export function actionLabel(
action: { actionType: string; metadata: Prisma.JsonValue },
currency: string,
): string {
const fallback = ACTION_LABELS[action.actionType] ?? action.actionType;
if (action.actionType === "PARTIAL_PAYMENT_CONFIRMED") {
const amount = (action.metadata as { paymentAmount?: unknown } | null)?.paymentAmount;
if (typeof amount === "number" && Number.isFinite(amount)) {
return `Partial payment of ${formatCurrency(amount, currency)} confirmed`;
}
}
return fallback;
}