Files
Voiced/src/lib/types.ts
T
xavierk 74ba04e17f Add Rust logo pipeline: trim, metrics, knockout and Branding settings
Logos (PNG, JPEG, WebP) are decoded, trimmed to their ink box, downscaled
to 1200 px and re-encoded as a content-addressed print PNG plus a white
knockout variant when the logo has alpha; aspect, ink density, mean colour
and kind (wordmark, mark, tall) are stored with the settings and frozen in
the issue snapshot. Legacy logos are derived at startup. The Arun P logo
PDF shrinks from 334 KB to 92 KB. Settings gains a Branding section with
white and dark previews and a business-name toggle (migration M5).
2026-10-04 06:31:30 +05:30

233 lines
6.4 KiB
TypeScript

export type TaxType = "none" | "cgst_sgst" | "igst";
export type LineMode = "fixed" | "rate";
export type LineUnit = "second" | "minute" | "hour" | "session" | "unit";
export interface Settings {
vendorName: string;
vendorAddress: string;
vendorEmail: string;
vendorPhone: string;
vendorPan: string;
vendorGstin: string;
vendorStateCode: string;
logoPath: string | null;
signaturePath: string | null;
defaultBankId: number | null;
defaultTaxRate: number;
defaultTaxType: TaxType;
paymentTermsDays: number;
currency: string;
onboarded: boolean;
theme: string;
gstRegistration: GstRegistration;
defaultHsnSac: string;
signatoryName: string;
signatoryDesignation: string;
/** The user's default page setup (RenderPrefsV1 JSON); empty means the built-in defaults. */
renderPrefs: string;
/** Folder of the last export; kept by the backend (saving settings does not change it). */
lastExportDir?: string;
/** The untouched logo file the derived images came from. */
logoOriginalPath: string | null;
/** White-ink variant for dark surfaces; only for logos with transparency. */
logoKnockoutPath: string | null;
/** LogoMeta JSON from the import pipeline; empty until the logo has been through it. */
logoMeta: string;
/** Whether the logo already contains the business name. Automatic means a wordmark does. */
logoIncludesName: "auto" | "yes" | "no";
}
export interface BankAccount {
id: number | null;
label: string;
bankName: string;
accountName: string;
accountNo: string;
branch: string;
ifsc: string;
isDefault: boolean;
}
export interface InvoiceSeries {
id: number;
prefix: string;
padding: number;
nextNumber: number;
isActive: boolean;
createdAt: string;
nextInvoiceNumber: string;
}
export interface Client {
id: number | null;
name: string;
address: string;
gstin: string;
stateCode: string;
poNumber: string;
createdAt: string;
}
export interface InvoiceItem {
id?: number | null;
description: string;
mode: LineMode;
rate: number;
unit: LineUnit;
quantity: number;
amount: number;
sortOrder: number;
/** Optional so older callers that build items by hand keep compiling; stored as "" when absent. */
hsnSac?: string;
}
export type GstRegistration = "unregistered" | "regular";
/** What the webview sends to issue an invoice; totals, tax and words are derived in Rust. */
export interface InvoiceInput {
invoiceDate: string;
dueDate: string;
clientId: number | null;
clientName: string;
clientAddress: string;
clientGstin: string;
poNumber: string;
placeOfSupplyStateCode: string;
discount: number;
taxType: TaxType;
taxRate: number;
reverseCharge: boolean;
bankAccountId: number | null;
signaturePath: string | null;
notes: string;
saveClient: boolean;
draftId: number | null;
items: InvoiceItem[];
}
export type InvoiceStatus = "draft" | "issued" | "cancelled";
/** An invoice as stored: all amounts are derived on the Rust side. */
export interface Invoice {
id: number;
number: string;
seriesId: number | null;
invoiceDate: string;
dueDate: string;
clientId: number | null;
clientName: string;
clientAddress: string;
clientGstin: string;
poNumber: string;
placeOfSupplyStateCode: string;
subtotal: number;
discount: number;
taxType: TaxType;
taxRate: number;
cgstAmount: number;
sgstAmount: number;
igstAmount: number;
total: number;
amountInWords: string;
bankAccountId: number | null;
bankSnapshot: string;
signaturePath: string | null;
notes: string;
status: InvoiceStatus;
createdAt: string;
updatedAt: string;
docType: "invoice" | "tax_invoice";
reverseCharge: boolean;
/** JSON of the supplier details at issue time; empty when unknown. */
vendorSnapshot: string;
snapshotOrigin: string;
cancelledAt: string | null;
cancelReason: string;
archivedPdfSha256: string | null;
/** RenderPrefsV1 JSON frozen at issue; empty when none was stored. */
renderPrefs: string;
/** Layout fingerprint of the archived PDF; null when nothing is archived. */
archivedFingerprint?: string | null;
archivedAt?: string | null;
items: InvoiceItem[];
}
export interface DraftSummary {
id: number;
updatedAt: string;
clientName: string | null;
total: number | null;
}
export interface InvoiceSummary {
id: number;
number: string;
invoiceDate: string;
dueDate: string;
clientName: string;
total: number;
status: InvoiceStatus;
createdAt: string;
}
export const EMPTY_ITEM: InvoiceItem = {
description: "",
mode: "fixed",
rate: 0,
unit: "unit",
quantity: 1,
amount: 0,
sortOrder: 0,
hsnSac: "",
};
/** GST state codes, same list as STATES in src-tauri/src/gst.rs (from India Compliance). */
export const INDIAN_STATES: { code: string; name: string }[] = [
{ code: "01", name: "Jammu and Kashmir" },
{ code: "02", name: "Himachal Pradesh" },
{ code: "03", name: "Punjab" },
{ code: "04", name: "Chandigarh" },
{ code: "05", name: "Uttarakhand" },
{ code: "06", name: "Haryana" },
{ code: "07", name: "Delhi" },
{ code: "08", name: "Rajasthan" },
{ code: "09", name: "Uttar Pradesh" },
{ code: "10", name: "Bihar" },
{ code: "11", name: "Sikkim" },
{ code: "12", name: "Arunachal Pradesh" },
{ code: "13", name: "Nagaland" },
{ code: "14", name: "Manipur" },
{ code: "15", name: "Mizoram" },
{ code: "16", name: "Tripura" },
{ code: "17", name: "Meghalaya" },
{ code: "18", name: "Assam" },
{ code: "19", name: "West Bengal" },
{ code: "20", name: "Jharkhand" },
{ code: "21", name: "Odisha" },
{ code: "22", name: "Chhattisgarh" },
{ code: "23", name: "Madhya Pradesh" },
{ code: "24", name: "Gujarat" },
{ code: "26", name: "Dadra and Nagar Haveli and Daman and Diu" },
{ code: "27", name: "Maharashtra" },
{ code: "29", name: "Karnataka" },
{ code: "30", name: "Goa" },
{ code: "31", name: "Lakshadweep Islands" },
{ code: "32", name: "Kerala" },
{ code: "33", name: "Tamil Nadu" },
{ code: "34", name: "Puducherry" },
{ code: "35", name: "Andaman and Nicobar Islands" },
{ code: "36", name: "Telangana" },
{ code: "37", name: "Andhra Pradesh" },
{ code: "38", name: "Ladakh" },
{ code: "96", name: "Other Countries" },
{ code: "97", name: "Other Territory" },
];
export const UNIT_LABELS: Record<LineUnit, string> = {
second: "per second",
minute: "per minute",
hour: "per hour",
session: "per session",
unit: "per unit",
};