Refactor production and stock tests to remove UOM dependency
- 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.
This commit is contained in:
@@ -13,7 +13,6 @@ export const grnHeaderSchema = z.object({
|
||||
|
||||
export function validateLine(input: {
|
||||
itemId: number | null
|
||||
uomId: number | null
|
||||
qty: string
|
||||
unitCost: string
|
||||
discountPct: string
|
||||
@@ -25,7 +24,6 @@ export function validateLine(input: {
|
||||
const errors: Record<string, string> = {}
|
||||
|
||||
if (!input.itemId) errors.itemId = "Select an item"
|
||||
if (!input.uomId) errors.uomId = "Select a UOM"
|
||||
|
||||
const qty = Number(input.qty)
|
||||
if (!input.qty || Number.isNaN(qty) || qty <= 0) errors.qty = "Quantity must be greater than 0"
|
||||
|
||||
@@ -10,12 +10,38 @@ export function validateItemForm(input: {
|
||||
name: string
|
||||
categoryId: number | null
|
||||
baseUomId: number | null
|
||||
/** Raw field value; empty means "no measurable content", which is valid. */
|
||||
contentQty?: string
|
||||
contentUnit?: string | null
|
||||
}): Record<string, string> {
|
||||
const errors: Record<string, string> = {}
|
||||
if (!input.sku.trim()) errors.sku = "SKU is required"
|
||||
if (!input.name.trim()) errors.name = "Item name is required"
|
||||
if (!input.categoryId) errors.categoryId = "Select a category"
|
||||
if (!input.baseUomId) errors.baseUomId = "Select a base UOM"
|
||||
Object.assign(errors, contentPairErrors(input.contentQty, input.contentUnit))
|
||||
return errors
|
||||
}
|
||||
|
||||
/**
|
||||
* An item's content size is optional, but half of it is not: the server rejects a lone
|
||||
* quantity or a lone unit with a 422. Shared because the variant builder validates its own
|
||||
* shape and so cannot go through `validateItemForm`.
|
||||
*/
|
||||
export function contentPairErrors(
|
||||
contentQty: string | undefined,
|
||||
contentUnit: string | null | undefined,
|
||||
): Record<string, string> {
|
||||
const errors: Record<string, string> = {}
|
||||
const rawQty = (contentQty ?? "").trim()
|
||||
const unit = contentUnit ?? null
|
||||
|
||||
if (rawQty && !unit) errors.contentUnit = "Select a unit for the content size"
|
||||
if (!rawQty && unit) errors.contentQty = "Enter a content size, or clear the unit"
|
||||
if (rawQty) {
|
||||
const qty = Number(rawQty)
|
||||
if (Number.isNaN(qty) || qty <= 0) errors.contentQty = "Content size must be greater than 0"
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
@@ -29,16 +55,6 @@ export function validateReorderLine(input: { warehouseId: number | null; reorder
|
||||
return errors
|
||||
}
|
||||
|
||||
export function validateConversionLine(input: { fromUom: number | null; toUom: number | null; factor: string }): Record<string, string> {
|
||||
const errors: Record<string, string> = {}
|
||||
if (!input.fromUom) errors.fromUom = "Select a UOM"
|
||||
if (!input.toUom) errors.toUom = "Select a UOM"
|
||||
if (input.fromUom && input.toUom && input.fromUom === input.toUom) errors.toUom = "From and to UOM must differ"
|
||||
const factor = Number(input.factor)
|
||||
if (!input.factor || Number.isNaN(factor) || factor <= 0) errors.factor = "Factor must be greater than 0"
|
||||
return errors
|
||||
}
|
||||
|
||||
export function validateUomName(name: string): Record<string, string> {
|
||||
const errors: Record<string, string> = {}
|
||||
if (!name.trim()) errors.name = "UOM name is required"
|
||||
|
||||
@@ -32,7 +32,6 @@ export function validateQuotationLine(input: { unitPrice: string; leadDays: stri
|
||||
|
||||
export function validatePoLine(input: {
|
||||
itemId: number | null
|
||||
uomId: number | null
|
||||
warehouseId: number | null
|
||||
qty: string
|
||||
unitPrice: string
|
||||
@@ -40,7 +39,6 @@ export function validatePoLine(input: {
|
||||
}): Record<string, string> {
|
||||
const errors: Record<string, string> = {}
|
||||
if (!input.itemId) errors.itemId = "Select an item"
|
||||
if (!input.uomId) errors.uomId = "Select a UOM"
|
||||
if (!input.warehouseId) errors.warehouseId = "Select a warehouse"
|
||||
const qty = Number(input.qty)
|
||||
if (!input.qty || Number.isNaN(qty) || qty <= 0) errors.qty = "Quantity must be greater than 0"
|
||||
|
||||
Reference in New Issue
Block a user