e7b1f270a5
- Implemented VendorOptionalFields component to handle optional vendor details (mobile, email, address) with validation. - Created useCustomerConfig hook to load optional customer field settings from Sales configuration. - Developed useProcurementConfig hook to manage Procurement configuration flags. - Introduced accessConfigApi for managing access configuration settings. - Added openingBalancesApi for handling opening balances operations. - Created procurementConfigApi for managing procurement configuration settings. - Implemented nav-routes for permission-based routing. - Developed PDF generation for purchase orders with dynamic vendor and item details. - Added purchase-order tax helpers for tax calculations and formatting. - Defined types for opening balances and related operations.
34 lines
1.4 KiB
TypeScript
34 lines
1.4 KiB
TypeScript
// Purchase-order tax helpers. The UI works in percent (18 for 18%) because that is how an item's
|
|
// tax rate is stored (`taxRatePercentage`) and how people say it; the PO API carries the rate as a
|
|
// fraction 0..1 (0.18) and a stored amount. The server recomputes and stores the amount itself, so
|
|
// these figures are for display and live totals only.
|
|
|
|
/** 18 -> 0.18. Four decimals, the precision the API stores. */
|
|
export function pctToRate(pct: number): number {
|
|
if (!Number.isFinite(pct) || pct <= 0) return 0
|
|
return Math.round(pct * 100) / 10000
|
|
}
|
|
|
|
/** 0.18 -> 18. */
|
|
export function rateToPct(rate: number): number {
|
|
if (!Number.isFinite(rate) || rate <= 0) return 0
|
|
return Math.round(rate * 10000) / 100
|
|
}
|
|
|
|
/**
|
|
* Tax amount for a line: qty x unit price x pct%, rounded half-up to 2 dp like the server
|
|
* (`PurchaseOrderService.TaxAmountFor`). The epsilon keeps 1.005-style products from rounding down.
|
|
*/
|
|
export function lineTaxAmount(qty: number, unitPrice: number, pct: number): number {
|
|
const q = Number(qty)
|
|
const p = Number(unitPrice)
|
|
const t = Number(pct)
|
|
if (![q, p, t].every(Number.isFinite) || q <= 0 || p < 0 || t <= 0) return 0
|
|
return Math.round(q * p * t + 1e-9) / 100
|
|
}
|
|
|
|
/** The text of a percent for an input box: 18 -> "18", 8.25 -> "8.25", 0 -> "0". */
|
|
export function pctText(pct: number | null | undefined): string {
|
|
return pct === null || pct === undefined || !Number.isFinite(pct) ? "0" : String(pct)
|
|
}
|