Files
ERP-core/Frontend/erp-system/lib/sales-validation.ts
T
2026-08-07 15:28:25 +05:30

102 lines
3.7 KiB
TypeScript

type SalesEditableLine = {
itemId: number
uomId: number
warehouseId: number
qty: number
freeQty: number
unitPrice?: number | null
discountPct?: number
taxPct?: number
}
type SalesDocumentValidationInput = {
customerId: number | null
warehouseId: number | null
cashierUserId?: number | null
requireCashierUser?: boolean
lines: SalesEditableLine[]
lineLabel?: string
}
type BundleEditableLine = {
itemId: number
uomId: number
qty: number
unitPrice: number
}
type BundleValidationInput = {
customerId: number | null
warehouseId: number | null
cashierUserId: number | null
templateId: number | null
bundleName: string
bundlePrice: number
lines: BundleEditableLine[]
}
function invalidNumber(value: number | null | undefined) {
return value === null || value === undefined || !Number.isFinite(value)
}
export function validateSalesDocument(input: SalesDocumentValidationInput): string | null {
const {
customerId,
warehouseId,
cashierUserId,
requireCashierUser = false,
lines,
lineLabel = "line",
} = input
if (!customerId) return "Select a customer."
if (!warehouseId) return "Select a warehouse."
if (requireCashierUser && !cashierUserId) return "Select a cashier."
if (lines.length === 0) return `Add at least one ${lineLabel}.`
for (const [index, line] of lines.entries()) {
const row = index + 1
if (!line.itemId) return `Select an item for ${lineLabel} ${row}.`
if (!line.uomId) return `Select a valid UOM for ${lineLabel} ${row}.`
if (!line.warehouseId) return `Select a warehouse for ${lineLabel} ${row}.`
if (warehouseId && line.warehouseId !== warehouseId) {
return `${lineLabel[0]?.toUpperCase() ?? "L"}${lineLabel.slice(1)} ${row} warehouse must match the selected header warehouse.`
}
if (invalidNumber(line.qty) || line.qty <= 0) return `Enter a quantity greater than zero for ${lineLabel} ${row}.`
if (invalidNumber(line.freeQty) || line.freeQty < 0) return `Enter a valid free quantity for ${lineLabel} ${row}.`
if (line.unitPrice !== null && line.unitPrice !== undefined && (invalidNumber(line.unitPrice) || line.unitPrice < 0)) {
return `Enter a valid unit price for ${lineLabel} ${row}.`
}
if (line.discountPct !== undefined && (invalidNumber(line.discountPct) || line.discountPct < 0 || line.discountPct > 100)) {
return `Enter a discount percentage between 0 and 100 for ${lineLabel} ${row}.`
}
if (line.taxPct !== undefined && (invalidNumber(line.taxPct) || line.taxPct < 0 || line.taxPct > 100)) {
return `Enter a tax percentage between 0 and 100 for ${lineLabel} ${row}.`
}
}
return null
}
export function validateBundleSale(input: BundleValidationInput): string | null {
const { customerId, warehouseId, cashierUserId, templateId, bundleName, bundlePrice, lines } = input
if (!customerId) return "Select a customer."
if (!warehouseId) return "Select a warehouse."
if (!cashierUserId) return "Select a cashier."
if (!templateId) return "Select a bundle template."
if (!bundleName.trim()) return "Enter a bundle name."
if (invalidNumber(bundlePrice) || bundlePrice < 0) return "Enter a valid bundle price."
if (lines.length === 0) return "Add at least one bundle component line."
for (const [index, line] of lines.entries()) {
const row = index + 1
if (!line.itemId) return `Select an item for component line ${row}.`
if (!line.uomId) return `Select a valid UOM for component line ${row}.`
if (invalidNumber(line.qty) || line.qty <= 0) return `Enter a quantity greater than zero for component line ${row}.`
if (invalidNumber(line.unitPrice) || line.unitPrice < 0) return `Enter a valid unit price for component line ${row}.`
}
return null
}