diff --git a/src/services/flowaccount.ts b/src/services/flowaccount.ts index df40d27..0c46f50 100644 --- a/src/services/flowaccount.ts +++ b/src/services/flowaccount.ts @@ -289,13 +289,55 @@ const flowAccount = { const quotation = data.quotation; const customer = quotation.customerBranch; - const product = + + const summary = { + subTotal: 0, + discountAmount: 0, + vatableAmount: 0, + exemptAmount: 0, + vatAmount: 0, + grandTotal: 0, + }; + + const products = ( quotation.payCondition === PayCondition.BillFull || quotation.payCondition === PayCondition.Full ? quotation.productServiceList : quotation.productServiceList.filter((lhs) => data.installments.some((rhs) => rhs.no === lhs.installmentNo), - ); + ) + ).map((v) => { + // TODO: Use product's VAT field (not implemented) instead. + const VAT_RATE = VAT_DEFAULT; + + summary.subTotal += + precisionRound(v.pricePerUnit * (1 + (v.vat > 0 ? VAT_RATE : 0))) * v.amount; + summary.discountAmount += v.discount; + + const total = + precisionRound(v.pricePerUnit * (1 + (v.vat > 0 ? VAT_RATE : 0))) * v.amount - + (v.discount ?? 0); + + if (v.vat > 0) { + summary.vatableAmount += precisionRound(total / (1 + VAT_RATE)); + summary.vatAmount += v.vat; + } else { + summary.exemptAmount += total; + } + + summary.grandTotal += total; + + return { + type: ProductAndServiceType.ProductNonInv, + name: v.product.name, + pricePerUnit: precisionRound(v.pricePerUnit), + quantity: v.amount, + discountAmount: v.discount, + vatRate: v.vat === 0 ? 0 : Math.round(VAT_RATE * 100), + total, + }; + }); + const payload = { contactCode: customer.code, contactName: customer.contactName || "-", @@ -333,45 +375,12 @@ const flowAccount = { discounPercentage: 0, discountAmount: quotation.totalDiscount, - subTotal: - quotation.payCondition === "BillSplitCustom" || - quotation.payCondition === "BillSplit" || - quotation.payCondition === "SplitCustom" || - quotation.payCondition === "Split" - ? 0 - : quotation.totalPrice, - vatableAmount: - quotation.payCondition === "BillSplitCustom" || - quotation.payCondition === "BillSplit" || - quotation.payCondition === "SplitCustom" || - quotation.payCondition === "Split" - ? 0 - : quotation.totalPrice - quotation.totalDiscount - quotation.vatExcluded, - exemptAmount: - quotation.payCondition === "BillSplitCustom" || - quotation.payCondition === "BillSplit" || - quotation.payCondition === "SplitCustom" || - quotation.payCondition === "Split" - ? 0 - : quotation.vatExcluded, - totalAfterDiscount: - quotation.payCondition === "BillSplitCustom" || - quotation.payCondition === "BillSplit" || - quotation.payCondition === "SplitCustom" || - quotation.payCondition === "Split" - ? 0 - : quotation.finalPrice, - vatAmount: - quotation.payCondition === "BillSplitCustom" || - quotation.payCondition === "BillSplit" || - quotation.payCondition === "SplitCustom" || - quotation.payCondition === "Split" - ? 0 - : quotation.vat, - grandTotal: - quotation.payCondition === "BillSplitCustom" || quotation.payCondition === "SplitCustom" - ? data.installments.reduce((a, c) => a + c.amount, 0) - : quotation.finalPrice, + subTotal: summary.subTotal, + totalAfterDiscount: summary.subTotal - summary.discountAmount, + vatableAmount: summary.vatableAmount, + exemptAmount: summary.exemptAmount, + vatAmount: summary.vatAmount, + grandTotal: summary.grandTotal, remarks: htmlToText( convertTemplate(quotation.remark ?? "", { @@ -389,17 +398,7 @@ const flowAccount = { }, }), ), - items: product.map((v) => ({ - type: ProductAndServiceType.ProductNonInv, - name: v.product.name, - pricePerUnit: precisionRound(v.pricePerUnit), - quantity: v.amount, - discountAmount: v.discount, - total: - precisionRound(v.pricePerUnit * (1 + (v.vat > 0 ? VAT_DEFAULT : 0))) * v.amount - - (v.discount ?? 0), - vatRate: v.vat === 0 ? 0 : Math.round(VAT_DEFAULT * 100), - })), + items: products, }; return await flowAccountAPI.createReceipt(payload, false);