invoice-calculation-samj296
v2.1.0
Published
A reusable invoice calculation engine used in my construction billing system.
Readme
Invoice Calculation Engine
A lightweight, reusable calculation module published as an NPM package. This package powers the invoice calculation logic used in my Construction Billing System (frontend + backend).
It centralizes all business logic for:
- Subtotal calculation
- Line‑item discount calculation
- Bill‑level discount calculation
- Ordered, compound‑safe tax calculation
- Grand total calculation
- Holdback and due‑amount logic
- Safe numeric sanitization
By extracting this logic into a standalone NPM package, both the frontend and backend use the exact same calculation rules, ensuring consistency and eliminating duplicated code.
This package exists to solve a real architectural problem:
Reason for creating this package
My billing system has two separate codebases (frontend + backend).
I needed one shared source of truth for invoice calculations.Publishing this as an NPM package allows:
- Consistent invoice totals across all apps
- Easy updates through versioning
- Clean separation of business logic
- Reusable logic for future projects
- Professional modular architecture
- Zero duplication of calculation logic
This module is used inside my Construction Billing System, a full-stack project built with
- React Frontend
- Node.js + Express backend
- MongoDB
- JWT authentication
- Multi-tenant architecture
By publishing this logic as an NPM package, I ensure:
- Both frontend and backend always stay in sync
- Updates happen in one place
- The system remains clean and scalable
Installation
npm install invoice-calculationUsage
import calculateFunction from "invoice-calculation";Item Format
Each item must contain
{
quantity: number,
rate: number,
disc: {
type: "flat" | "percent",
value: number
}
}
Example:
const items = [
{
quantity: 2,
rate: 100,
disc: {
enabled: true,
type: "percent",
value: 10
}
},
{
quantity: 1,
rate: 250,
disc: {
enabled: false,
type: "flat",
value: 0
}
}
]Bill-Level Discount Format
const disc = {
status: true, //enable/disable bill-level discount
type: "flat", // "flat" | "percent" (you can use DiscType.flat or DiscType.percent)
value: 50
};Prepare your tax configuration
taxes must include:
namepercentorder(determines calculation order)
const taxConfig = [
{name: "GST", percent: 10, order: 1},
{name: "PST", percent: 7, order: 2}
];Calculate totals
const result = calculateFunction(items, taxConfig, disc);
console.log(result);Output
{
amountBeforeDisc: number, //subtotal before any discount
itemDisc: number, //total line-item discount
amountAfterItemDisc: number, //subtotal after line-item discount
billDisc: number, //bill-level discount
amountAfterDisc: number, //subtotal after all discounts
taxes: [
{name, percent, taxAmount}
],
amountAfterTax: number //final grand total
}How it works
- Calculates subtotal from item quantities x rate
- Applies line-item discounts
- Calculates bill-level discount on the discounted subtotal
- Sorts taxes by order
- Applies each tax sequentially
- Returns subtotal, discount breakdown, tax breakdown, and grand total
The logic is pure, meaning:
- No API calls
- No external dependencies
- No side effects
- Fully deterministic
This makes the package easy to test, maintain, and reuse.
Additional Utilities
Line-item discount helper
lineItemDisc(item)Holdback amount
calculateHoldBackAmount(total, percent)Due amount
calculateDueAmount(total, paidAmount, holdBackAmount, holdBackDate)Safe numeric sanitization
sanitizeNumber("123")
// { error: false, data: 123, message: null }
sanitizeNumber("abc")
// { error: true, data:0, message: "Invalid number: abc" }License
MIT License
