Initial commit: Voiced invoice desktop app
Offline-first invoicing app for Test Vendor, built by Bongbetic. - Tauri v2 (Rust) + React/TypeScript + IBM Carbon Design System UI - SQLite (rusqlite) storage with a persistent invoice-number series - Guided first-run setup, pre-filled vendor/bank details - Fixed-amount or rate x quantity line items (per sec/min/hour/session/unit) - GST as CGST+SGST or IGST, Indian amount-in-words - Optional signature, with a computer-generated note as fallback - Print-ready PDF export via @react-pdf/renderer - Windows cross-compile via cargo-xwin (NSIS installer) Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import { round2 } from "./format";
|
||||
import type { InvoiceItem, TaxType } from "./types";
|
||||
|
||||
/** Amount for a single line: a fixed total, or rate × quantity. */
|
||||
export function computeLineAmount(item: InvoiceItem): number {
|
||||
if (item.mode === "rate") {
|
||||
return round2((item.rate || 0) * (item.quantity || 0));
|
||||
}
|
||||
return round2(item.amount || 0);
|
||||
}
|
||||
|
||||
export interface Totals {
|
||||
subtotal: number;
|
||||
discount: number;
|
||||
taxable: number;
|
||||
cgst: number;
|
||||
sgst: number;
|
||||
igst: number;
|
||||
taxTotal: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export function computeTotals(
|
||||
items: InvoiceItem[],
|
||||
discount: number,
|
||||
taxType: TaxType,
|
||||
taxRate: number,
|
||||
): Totals {
|
||||
const subtotal = round2(items.reduce((sum, item) => sum + computeLineAmount(item), 0));
|
||||
const discountValue = round2(Math.min(Math.max(discount || 0, 0), subtotal));
|
||||
const taxable = round2(subtotal - discountValue);
|
||||
|
||||
let cgst = 0;
|
||||
let sgst = 0;
|
||||
let igst = 0;
|
||||
if (taxType === "cgst_sgst") {
|
||||
cgst = round2((taxable * (taxRate / 2)) / 100);
|
||||
sgst = round2((taxable * (taxRate / 2)) / 100);
|
||||
} else if (taxType === "igst") {
|
||||
igst = round2((taxable * taxRate) / 100);
|
||||
}
|
||||
const taxTotal = round2(cgst + sgst + igst);
|
||||
|
||||
return {
|
||||
subtotal,
|
||||
discount: discountValue,
|
||||
taxable,
|
||||
cgst,
|
||||
sgst,
|
||||
igst,
|
||||
taxTotal,
|
||||
total: round2(taxable + taxTotal),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user