updates
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* useDocumentTotals
|
||||
*
|
||||
* Pure calculation hook for invoice-style documents (invoices, bills, estimates,
|
||||
* credit notes, vendor credits, etc.).
|
||||
*
|
||||
* Inputs
|
||||
* ────────────────────────────────────────────────────────────────────────────
|
||||
* lineItems – flat array of all items (parts + services + expenses)
|
||||
* discountType – 'no' | 'line_item_level' | 'transaction_level'
|
||||
* discountAmount – used when discountType === 'transaction_level'
|
||||
* taxRate – percentage (e.g. 15 for 15 %). Undefined → no tax.
|
||||
*
|
||||
* Calculation order
|
||||
* ────────────────────────────────────────────────────────────────────────────
|
||||
* 1. subTotal = Σ (qty × rate)
|
||||
* 2. lineItemDiscount = Σ discount_amount (only when discountType === 'line_item_level')
|
||||
* 3. transactionDiscount = discountAmount (only when discountType === 'transaction_level')
|
||||
* 4. totalDiscount = lineItemDiscount + transactionDiscount
|
||||
* 5. afterDiscount = subTotal - totalDiscount
|
||||
* 6. taxAmount = afterDiscount × (taxRate / 100)
|
||||
* 7. total = afterDiscount + taxAmount
|
||||
*/
|
||||
|
||||
export type DocumentLineItem = {
|
||||
quantity: number
|
||||
rate: number
|
||||
discount_amount?: number
|
||||
}
|
||||
|
||||
export type UseDocumentTotalsInput = {
|
||||
lineItems: DocumentLineItem[]
|
||||
discountType?: string | null
|
||||
discountAmount?: number
|
||||
taxRate?: number
|
||||
}
|
||||
|
||||
export type DocumentTotals = {
|
||||
subTotal: number
|
||||
lineItemDiscount: number
|
||||
transactionDiscount: number
|
||||
totalDiscount: number
|
||||
afterDiscount: number
|
||||
taxAmount: number
|
||||
total: number
|
||||
hasLineItems: boolean
|
||||
}
|
||||
|
||||
export function useDocumentTotals({
|
||||
lineItems,
|
||||
discountType,
|
||||
discountAmount,
|
||||
taxRate,
|
||||
}: UseDocumentTotalsInput): DocumentTotals {
|
||||
const subTotal = lineItems.reduce((sum, item) => {
|
||||
const qty = Number(item.quantity) || 0
|
||||
const rate = Number(item.rate) || 0
|
||||
return sum + qty * rate
|
||||
}, 0)
|
||||
|
||||
const lineItemDiscount =
|
||||
discountType === "line_item_level"
|
||||
? lineItems.reduce((sum, item) => sum + (Number(item.discount_amount) || 0), 0)
|
||||
: 0
|
||||
|
||||
const transactionDiscount =
|
||||
discountType === "transaction_level" ? Number(discountAmount) || 0 : 0
|
||||
|
||||
const totalDiscount = lineItemDiscount + transactionDiscount
|
||||
const afterDiscount = Math.max(0, subTotal - totalDiscount)
|
||||
const taxAmount = taxRate ? afterDiscount * (taxRate / 100) : 0
|
||||
const total = afterDiscount + taxAmount
|
||||
|
||||
return {
|
||||
subTotal,
|
||||
lineItemDiscount,
|
||||
transactionDiscount,
|
||||
totalDiscount,
|
||||
afterDiscount,
|
||||
taxAmount,
|
||||
total,
|
||||
hasLineItems: lineItems.length > 0,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user