15ddac178c
- Updated production.spec.ts, stock-adjustments.spec.ts, and stock-transfers.spec.ts to eliminate UOM references in API seeder and test cases. - Adjusted ApiSeeder methods to remove UOM parameters from stock receiving and production template creation. - Revised documentation to reflect changes in UOM handling, emphasizing that stock is counted in base UOM only. - Introduced new enums for MeasureUnit and StageQtyUnit to clarify content size and stage input quantities. - Implemented ItemContent service to validate and normalize content sizes. - Updated smoke tests to validate production stage inputs expressed in content units, ensuring correct consumption calculations. - Modified frontend UOM label handling to reflect the removal of per-line UOMs in document lines.
47 lines
1.8 KiB
TypeScript
47 lines
1.8 KiB
TypeScript
// Document lines carry no UOM of their own: every quantity in the system is a count of the
|
|
// item's base UOM (FR-MD-02/03). Screens that used to render a per-line UOM picker now show
|
|
// the unit as a derived, read-only label — the user still needs to know that "12" means
|
|
// 12 bottles, they just cannot change it.
|
|
|
|
import { ItemListItem, Uom } from "@/types/master-data"
|
|
|
|
/** Minimal shapes so this works with both `Item` and `ItemListItem`. */
|
|
type ItemLike = Pick<ItemListItem, "itemId" | "baseUomId">
|
|
|
|
/**
|
|
* Display name of an item's base UOM, e.g. "BOTTLE". Returns an em dash when no item is
|
|
* selected yet, and falls back to the raw id if the UOM list has not loaded.
|
|
*/
|
|
export function baseUomLabel(
|
|
items: readonly ItemLike[],
|
|
uoms: readonly Uom[],
|
|
itemId: number | null | undefined,
|
|
): string {
|
|
if (!itemId) return "—"
|
|
const item = items.find((candidate) => candidate.itemId === itemId)
|
|
if (!item) return "—"
|
|
return uoms.find((u) => u.uomId === item.baseUomId)?.name ?? `#${item.baseUomId}`
|
|
}
|
|
|
|
/**
|
|
* Display name for a UOM id that may be absent — an intermediate production output's WIP
|
|
* label, which is null on any output that references a real item.
|
|
*/
|
|
export function uomLabel(uoms: readonly Uom[], uomId: number | null | undefined): string {
|
|
if (!uomId) return "—"
|
|
return uoms.find((u) => u.uomId === uomId)?.name ?? `#${uomId}`
|
|
}
|
|
|
|
/**
|
|
* The unit an item's content is measured in — "ml" or "g" — or null when the item has no
|
|
* content size. Used to label a production input entered in content units.
|
|
*/
|
|
export function contentUnitLabel(
|
|
items: readonly Pick<ItemListItem, "itemId" | "contentBaseUnit">[],
|
|
itemId: number | null | undefined,
|
|
): string | null {
|
|
if (!itemId) return null
|
|
const unit = items.find((candidate) => candidate.itemId === itemId)?.contentBaseUnit
|
|
return unit ? unit.toLowerCase() : null
|
|
}
|