An invoice's total is calculated in this order:
Example: 2 items @ $100 each = $200 subtotal, 10% discount = $180, 19% tax on $180 = $34.20, +$5 fee = $219.20 total
Payments are applied individually to invoices:
When a payment exceeds the remaining invoice balance, the excess is automatically added to the client's credit balance:
Example: Invoice total = $200, already paid $150, remaining = $50. Client pays $80 → $50 applied to invoice (status → paid), $30 added to client balance.
The client's balance is then auto-applied to future invoices at creation time.
Product costs are snapshotted at invoice creation time:
unitCost at creationWhen a client has an outstanding balance (from overpayments), it automatically applies to new invoices. If new invoice = $500 and client balance = $100, the client owes only $400.
A client's balance is tracked cumulatively:
Payments are distributed in 3 priority steps:
Example: Invoice 1: $500 unpaid, Pending Balance: $200. Client pays $800 → Invoice 1 fully paid ($500), Pending Balance reduced by $200, Client Balance += $100.
Stock is tracked differently for simple and composite products:
Example: Chair (composite) needs 1 frame + 4 wheels. Available: 10 frames, 32 wheels → Effective qty = floor(min(10/1, 32/4)) = floor(min(10, 8)) = 8 chairs
Products are flagged as low stock when: Effective Quantity ≤ Minimum Stock (default minStock = 5)
When an invoice is created:
quantity -= item.quantityquantity -= (component.quantity_needed × item.quantity)⚠️ Stock deduction is atomic: If validation passes, deduction WILL succeed. If validation fails, invoice creation is blocked entirely.
SKUs are auto-generated during creation or category change:
SKU = [Category Prefix] + [Sequence Number]
Example: Category "Furniture" with 3 existing products → new product gets SKU "Furniture-4"
Fixed amount expenses included in reports only if date is within report period. No pro-ration applied.
Stored as a rate and pro-rated based on recurrence pattern:
| Recurrence | Formula | Example |
|---|---|---|
| Weekly | rate × (days ÷ 7) | $100/week × 10 days = $142.86 |
| Monthly | rate × months (calendar-accurate) | $1000/month × 1.5 months = $1500 |
| Quarterly | rate × (months ÷ 3) | $3000/quarter × 2 months = $2000 |
| Yearly | rate × (days ÷ 365) | $12000/year × 100 days = $3287.67 |
When you have a monthly expense or salary, the system needs to figure out how many months fit between two dates. Instead of assuming every month has 30 days, it counts using the real calendar.
The idea is simple: split the date range into 3 parts:
Example: Feb 15 → Mar 17 (expense is $1,000/month)
Another example: Jan 1 → Mar 31
Base salary is calculated differently by employee's salary period:
Weekly
Salary = rate × (days ÷ 7)
$1000/week, 21 days (3 weeks) = $3000
Monthly
Salary = rate × calcMonths() [calendar-accurate]
$3000/month, Feb 15–Mar 17 (1.0484 months) = $3145.20
Advances reduce take-home pay, pro-rated by overlap between the advance's pay period and the report period:
Example: $3000/month employee, $500 advance on Jan 25. Period end = Jan 31. Remaining days = calcDays(Jan 25, Jan 31) = 7. Daily rate = $500 ÷ 7 = $71.43. If report covers full January: overlap = 7 days → Deduction = $71.43 × 7 = $500. Net salary: $3000 − $500 = $2500.
If report only covers Jan 25–Jan 28 (4 overlap days): Deduction = $71.43 × 4 = $285.71.
Every salary advance has one of 3 statuses:
When does it auto-change to "Deducted"?
What can you change manually?
Employees can have an inactive date that stops salary calculation from that date:
Example: Employee earns $3,000/month, hired Jan 1, inactive date = Feb 15. For a Jan 1 – Mar 31 report: salary is calculated for Jan 1 – Feb 15 only (1.5 months = $4,500), not the full 3 months.
Each supplier bill has a type that determines how it is treated in financial calculations:
Similar to invoices, supplier bills track:
daysOverdue = floor((now − dueDate) ÷ 86400000)
Aging categories: Current (0 days), 1-30, 31-60, 61-90, 90+
Import clients in bulk from an Excel or CSV file. Supported columns:
Import suppliers in bulk from an Excel or CSV file. Only details are imported — no bills are created. Supported columns:
Tax is calculated on the discounted amount:
Tax = (Subtotal − Discount) × (Tax Rate ÷ 100)
Default tax rate: 19%
Tax is calculated on all invoices within the report period:
Tax Collected = SUM(invoice.tax) for all invoices in period
Example: 3 invoices in January — $190 tax (paid), $95 tax (partially paid), $50 tax (draft) → Total tax = $335
Calculates profitability over a date range.
Snapshot of financial position.
Combines P&L with detailed breakdowns:
Both P&L and Comprehensive reports include a "Total Sales in Period" section with a Cash Out metric:
Why? Cash Out shows what you actually paid out as discrete payments, so you can compare it to the cash received (Total Paid) to see real cash flow.
Groups invoices by month (12-month lookback):
Trend % = ((current month − prior month) ÷ prior month) × 100
Green indicates positive trend, red indicates negative.
Counts new clients and invoices created after month start.
Lists products where Effective Quantity ≤ Minimum Stock Threshold.
⚠️ If validation fails, invoice is NOT created and error is shown.
| Value Type | Format | Example |
|---|---|---|
| Currency | 2 decimals with symbol | $1,234.56 |
| Percentage | 1 decimal place | 19.5% |
| Month (pro-ration) | 4 decimals (internal) | 1.5048 |
| Days | Integer (floor) | 30 |
| Quantity | 2 decimals or integer | 5 or 2.5 |
All actions are logged in Activity Log: invoice creation/update/delete, payments, expenses, stock adjustments, employee changes, advances.