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; } 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: "Sampleachal 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 = { second: "per second", minute: "per minute", hour: "per hour", session: "per session", unit: "per unit", };