Add toasts, Settings tabs, Clients page and item presets (Phase E1)
- Global Carbon toast stack replaces scattered inline notices; errors persist until closed. - Settings is split into eight tabs with one Save and a remembered last tab; Numbering embeds the series settings. - New Clients page with a DataTable, shared add/edit modal, structured addresses, GST category (informational), per-client notes and payment terms. The composed address string is kept for back-compat. Deleting a client warns about invoice count; issued invoices keep their own snapshot. - Migration M7 adds the client columns and item_presets; existing clients with a GSTIN are backfilled to registered_regular. - New invoice form: client ComboBox with type-ahead and inline create, client defaults applied on selection, and an Add from preset control. - Rust tests for M7 (fresh and v6 upgrade), client validation and CRUD, presets CRUD; vitest for the toast store and new helpers. PDF output and fingerprint goldens are unchanged. The new UI has not been run in a webview yet.
This commit is contained in:
@@ -58,16 +58,80 @@ export interface InvoiceSeries {
|
||||
nextInvoiceNumber: string;
|
||||
}
|
||||
|
||||
export type GstCategory = "registered_regular" | "unregistered" | "composition" | "sez" | "overseas";
|
||||
|
||||
/** Informational only; the tax heads still derive from supplier state and place of supply. */
|
||||
export const GST_CATEGORY_LABELS: Record<GstCategory, string> = {
|
||||
registered_regular: "Registered (regular)",
|
||||
unregistered: "Unregistered",
|
||||
composition: "Composition",
|
||||
sez: "SEZ",
|
||||
overseas: "Overseas",
|
||||
};
|
||||
|
||||
export interface Client {
|
||||
id: number | null;
|
||||
name: string;
|
||||
/** The composed multi-line address; what invoices store and print. */
|
||||
address: string;
|
||||
gstin: string;
|
||||
/** Doubles as the address state and the default place of supply. */
|
||||
stateCode: string;
|
||||
poNumber: string;
|
||||
createdAt: string;
|
||||
addressLine1: string;
|
||||
addressLine2: string;
|
||||
city: string;
|
||||
pincode: string;
|
||||
gstCategory: GstCategory;
|
||||
/** Notes / payment terms text copied onto a new invoice when the client is picked. */
|
||||
defaultNotes: string;
|
||||
/** Null means the settings default. */
|
||||
paymentTermsDays: number | null;
|
||||
/** Read-only: how many invoices reference this client. */
|
||||
invoiceCount?: number;
|
||||
}
|
||||
|
||||
export const blankClient = (): Client => ({
|
||||
id: null,
|
||||
name: "",
|
||||
address: "",
|
||||
gstin: "",
|
||||
stateCode: "",
|
||||
poNumber: "",
|
||||
createdAt: "",
|
||||
addressLine1: "",
|
||||
addressLine2: "",
|
||||
city: "",
|
||||
pincode: "",
|
||||
gstCategory: "unregistered",
|
||||
defaultNotes: "",
|
||||
paymentTermsDays: null,
|
||||
});
|
||||
|
||||
/** A saved line item. `ratePaise` is the amount for "fixed" and the per-unit rate for "rate". */
|
||||
export interface ItemPreset {
|
||||
id: number | null;
|
||||
description: string;
|
||||
hsnSac: string;
|
||||
mode: LineMode;
|
||||
unit: LineUnit;
|
||||
ratePaise: number;
|
||||
sortOrder: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export const blankPreset = (): ItemPreset => ({
|
||||
id: null,
|
||||
description: "",
|
||||
hsnSac: "",
|
||||
mode: "fixed",
|
||||
unit: "unit",
|
||||
ratePaise: 0,
|
||||
sortOrder: 0,
|
||||
createdAt: "",
|
||||
});
|
||||
|
||||
export interface InvoiceItem {
|
||||
id?: number | null;
|
||||
description: string;
|
||||
|
||||
Reference in New Issue
Block a user