hvp-shared 6.84.0 → 6.86.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Client Billing Enums
3
+ *
4
+ * Enums for the client-facing billing portal where pet owners
5
+ * request CFDI income invoices for their veterinary visits.
6
+ */
7
+ /**
8
+ * Status of a client invoice request through the processing pipeline.
9
+ */
10
+ export declare enum ClientInvoiceStatus {
11
+ /** Request created, not yet processing */
12
+ pending = "pending",
13
+ /** Background job is running (lookup, CFDI build, stamping) */
14
+ processing = "processing",
15
+ /** CFDI stamped successfully, PDF/XML available */
16
+ stamped = "stamped",
17
+ /** Processing failed (see errorMessage) */
18
+ failed = "failed",
19
+ /** Previous month invoice — requires admin/manager authorization */
20
+ requires_authorization = "requires_authorization"
21
+ }
22
+ /**
23
+ * Date rule applied to an invoice based on ticket date vs emission date.
24
+ */
25
+ export declare enum InvoiceDateRule {
26
+ /** Ticket date within 72h — stamp with original date */
27
+ within_72h = "within_72h",
28
+ /** Ticket date >72h ago, same fiscal month — stamp with today's date */
29
+ same_month = "same_month",
30
+ /** Ticket date >72h ago, previous fiscal month — requires authorization */
31
+ previous_month = "previous_month"
32
+ }
33
+ /**
34
+ * All ClientInvoiceStatus values as array (for dropdowns/filters)
35
+ */
36
+ export declare const CLIENT_INVOICE_STATUS_VALUES: ClientInvoiceStatus[];
37
+ /**
38
+ * ClientInvoiceStatus labels in Spanish (for UI)
39
+ */
40
+ export declare const CLIENT_INVOICE_STATUS_LABELS: Record<ClientInvoiceStatus, string>;
41
+ /**
42
+ * Petco (MASCOTAS Y COMPAÑIA) — different invoice email per branch.
43
+ * Only case that requires branch-specific emails.
44
+ */
45
+ export declare const PETCO_RFC = "MAS121116E51";
46
+ export declare const PETCO_BRANCH_EMAILS: Record<string, string>;
47
+ export declare const INVOICE_DATE_RULE_LABELS: Record<InvoiceDateRule, string>;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ /**
3
+ * Client Billing Enums
4
+ *
5
+ * Enums for the client-facing billing portal where pet owners
6
+ * request CFDI income invoices for their veterinary visits.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.INVOICE_DATE_RULE_LABELS = exports.PETCO_BRANCH_EMAILS = exports.PETCO_RFC = exports.CLIENT_INVOICE_STATUS_LABELS = exports.CLIENT_INVOICE_STATUS_VALUES = exports.InvoiceDateRule = exports.ClientInvoiceStatus = void 0;
10
+ /**
11
+ * Status of a client invoice request through the processing pipeline.
12
+ */
13
+ var ClientInvoiceStatus;
14
+ (function (ClientInvoiceStatus) {
15
+ /** Request created, not yet processing */
16
+ ClientInvoiceStatus["pending"] = "pending";
17
+ /** Background job is running (lookup, CFDI build, stamping) */
18
+ ClientInvoiceStatus["processing"] = "processing";
19
+ /** CFDI stamped successfully, PDF/XML available */
20
+ ClientInvoiceStatus["stamped"] = "stamped";
21
+ /** Processing failed (see errorMessage) */
22
+ ClientInvoiceStatus["failed"] = "failed";
23
+ /** Previous month invoice — requires admin/manager authorization */
24
+ ClientInvoiceStatus["requires_authorization"] = "requires_authorization";
25
+ })(ClientInvoiceStatus || (exports.ClientInvoiceStatus = ClientInvoiceStatus = {}));
26
+ /**
27
+ * Date rule applied to an invoice based on ticket date vs emission date.
28
+ */
29
+ var InvoiceDateRule;
30
+ (function (InvoiceDateRule) {
31
+ /** Ticket date within 72h — stamp with original date */
32
+ InvoiceDateRule["within_72h"] = "within_72h";
33
+ /** Ticket date >72h ago, same fiscal month — stamp with today's date */
34
+ InvoiceDateRule["same_month"] = "same_month";
35
+ /** Ticket date >72h ago, previous fiscal month — requires authorization */
36
+ InvoiceDateRule["previous_month"] = "previous_month";
37
+ })(InvoiceDateRule || (exports.InvoiceDateRule = InvoiceDateRule = {}));
38
+ /**
39
+ * All ClientInvoiceStatus values as array (for dropdowns/filters)
40
+ */
41
+ exports.CLIENT_INVOICE_STATUS_VALUES = Object.values(ClientInvoiceStatus);
42
+ /**
43
+ * ClientInvoiceStatus labels in Spanish (for UI)
44
+ */
45
+ exports.CLIENT_INVOICE_STATUS_LABELS = {
46
+ [ClientInvoiceStatus.pending]: "Pendiente",
47
+ [ClientInvoiceStatus.processing]: "Procesando",
48
+ [ClientInvoiceStatus.stamped]: "Facturada",
49
+ [ClientInvoiceStatus.failed]: "Error",
50
+ [ClientInvoiceStatus.requires_authorization]: "Requiere autorización",
51
+ };
52
+ /**
53
+ * Petco (MASCOTAS Y COMPAÑIA) — different invoice email per branch.
54
+ * Only case that requires branch-specific emails.
55
+ */
56
+ exports.PETCO_RFC = "MAS121116E51";
57
+ exports.PETCO_BRANCH_EMAILS = {
58
+ URBAN: "7132ger@petco.com.mx",
59
+ HARBOR: "7178ger@petco.com.mx",
60
+ MONTEJO: "7154ger@petco.com.mx",
61
+ };
62
+ exports.INVOICE_DATE_RULE_LABELS = {
63
+ [InvoiceDateRule.within_72h]: "Dentro de 72 horas",
64
+ [InvoiceDateRule.same_month]: "Mismo mes (>72h)",
65
+ [InvoiceDateRule.previous_month]: "Mes anterior",
66
+ };
@@ -24,3 +24,5 @@ export * from './payroll-features.constants';
24
24
  export * from './inventory-session.enums';
25
25
  export * from './documentation.enums';
26
26
  export * from './settlement.enums';
27
+ export * from './client-billing.enums';
28
+ export * from './sat-income-invoice';
@@ -40,3 +40,5 @@ __exportStar(require("./payroll-features.constants"), exports);
40
40
  __exportStar(require("./inventory-session.enums"), exports);
41
41
  __exportStar(require("./documentation.enums"), exports);
42
42
  __exportStar(require("./settlement.enums"), exports);
43
+ __exportStar(require("./client-billing.enums"), exports);
44
+ __exportStar(require("./sat-income-invoice"), exports);
@@ -0,0 +1,95 @@
1
+ /**
2
+ * SAT Catalog Constants for CFDI Income Invoices (Facturas de Ingreso)
3
+ *
4
+ * Based on SAT catalogs for electronic invoicing (CFDI 4.0).
5
+ * These are specific to income invoices — payroll catalogs are in sat-catalogs.ts.
6
+ *
7
+ * @see SAT Catalogs: http://omawww.sat.gob.mx/tramitesyservicios/Paginas/anexo_20_version3-3.htm
8
+ */
9
+ /**
10
+ * SAT Fiscal Regime codes applicable to invoice receivers (clients).
11
+ * Broader set than payroll (which only uses 605/616).
12
+ */
13
+ export declare const SATClientFiscalRegime: {
14
+ readonly GeneralLaw: "601";
15
+ readonly LegalPersonsNonProfit: "603";
16
+ readonly SalariesAndWages: "605";
17
+ readonly LeaseIncome: "606";
18
+ readonly TaxIncorporation: "612";
19
+ readonly WithoutFiscalObligations: "616";
20
+ readonly BusinessActivityIncome: "621";
21
+ readonly SimplifiedTrust: "625";
22
+ readonly SimplifiedTrustLegal: "626";
23
+ };
24
+ export type SATClientFiscalRegimeCode = (typeof SATClientFiscalRegime)[keyof typeof SATClientFiscalRegime];
25
+ /**
26
+ * Fiscal regime labels in Spanish for client portal dropdowns
27
+ */
28
+ export declare const SAT_CLIENT_FISCAL_REGIME_LABELS: Record<SATClientFiscalRegimeCode, string>;
29
+ /**
30
+ * Fiscal regimes array for dropdowns
31
+ */
32
+ export declare const SAT_CLIENT_FISCAL_REGIMES_ARRAY: {
33
+ code: SATClientFiscalRegimeCode;
34
+ label: string;
35
+ }[];
36
+ /**
37
+ * SAT CFDI Use codes applicable to income invoices for veterinary services/products.
38
+ * Subset of the full catalog — only codes relevant to HVP clients.
39
+ */
40
+ export declare const SATCfdiUse: {
41
+ readonly GeneralExpenses: "G03";
42
+ readonly MedicalExpenses: "D01";
43
+ readonly NoFiscalEffect: "S01";
44
+ readonly PeriodicPayments: "CP01";
45
+ readonly Acquisitions: "G01";
46
+ };
47
+ export type SATCfdiUseCode = (typeof SATCfdiUse)[keyof typeof SATCfdiUse];
48
+ /**
49
+ * CFDI Use labels in Spanish for client portal dropdowns
50
+ */
51
+ export declare const SAT_CFDI_USE_LABELS: Record<SATCfdiUseCode, string>;
52
+ /**
53
+ * CFDI Use array for dropdowns
54
+ */
55
+ export declare const SAT_CFDI_USE_ARRAY: {
56
+ code: SATCfdiUseCode;
57
+ label: string;
58
+ }[];
59
+ /**
60
+ * SAT Payment Form codes.
61
+ * Maps from QVET payment methods to SAT-compliant codes.
62
+ */
63
+ export declare const SATPaymentForm: {
64
+ readonly Cash: "01";
65
+ readonly NominalCheck: "02";
66
+ readonly ElectronicTransfer: "03";
67
+ readonly CreditCard: "04";
68
+ readonly ElectronicWallet: "05";
69
+ readonly ElectronicMoney: "06";
70
+ readonly DigitalVouchers: "08";
71
+ readonly DebitCard: "28";
72
+ readonly ServiceCard: "29";
73
+ readonly ToBeDefined: "99";
74
+ };
75
+ export type SATPaymentFormCode = (typeof SATPaymentForm)[keyof typeof SATPaymentForm];
76
+ /**
77
+ * Payment form labels in Spanish
78
+ */
79
+ export declare const SAT_PAYMENT_FORM_LABELS: Record<SATPaymentFormCode, string>;
80
+ /**
81
+ * Maps QVET payment method strings to SAT payment form codes.
82
+ * QVET uses Spanish descriptors (UPPERCASE from collections report); SAT uses numeric codes.
83
+ *
84
+ * Source: qvet_collections.paymentMethod actual values (verified from production data).
85
+ */
86
+ export declare const QVET_PAYMENT_METHOD_TO_SAT: Record<string, SATPaymentFormCode>;
87
+ /**
88
+ * Default SAT payment form when QVET payment method is unknown
89
+ */
90
+ export declare const DEFAULT_SAT_PAYMENT_FORM: SATPaymentFormCode;
91
+ /**
92
+ * Resolves a QVET payment method string to SAT payment form code.
93
+ * Falls back to "99" (Por definir) if unknown.
94
+ */
95
+ export declare function resolvePaymentForm(qvetPaymentMethod: string): SATPaymentFormCode;
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ /**
3
+ * SAT Catalog Constants for CFDI Income Invoices (Facturas de Ingreso)
4
+ *
5
+ * Based on SAT catalogs for electronic invoicing (CFDI 4.0).
6
+ * These are specific to income invoices — payroll catalogs are in sat-catalogs.ts.
7
+ *
8
+ * @see SAT Catalogs: http://omawww.sat.gob.mx/tramitesyservicios/Paginas/anexo_20_version3-3.htm
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.DEFAULT_SAT_PAYMENT_FORM = exports.QVET_PAYMENT_METHOD_TO_SAT = exports.SAT_PAYMENT_FORM_LABELS = exports.SATPaymentForm = exports.SAT_CFDI_USE_ARRAY = exports.SAT_CFDI_USE_LABELS = exports.SATCfdiUse = exports.SAT_CLIENT_FISCAL_REGIMES_ARRAY = exports.SAT_CLIENT_FISCAL_REGIME_LABELS = exports.SATClientFiscalRegime = void 0;
12
+ exports.resolvePaymentForm = resolvePaymentForm;
13
+ // ============================================================================
14
+ // Fiscal Regime - Client (c_RegimenFiscal)
15
+ // ============================================================================
16
+ /**
17
+ * SAT Fiscal Regime codes applicable to invoice receivers (clients).
18
+ * Broader set than payroll (which only uses 605/616).
19
+ */
20
+ exports.SATClientFiscalRegime = {
21
+ GeneralLaw: "601",
22
+ LegalPersonsNonProfit: "603",
23
+ SalariesAndWages: "605",
24
+ LeaseIncome: "606",
25
+ TaxIncorporation: "612", // RIF (being phased out)
26
+ WithoutFiscalObligations: "616",
27
+ BusinessActivityIncome: "621",
28
+ SimplifiedTrust: "625", // RESICO Personas Físicas
29
+ SimplifiedTrustLegal: "626", // RESICO Personas Morales
30
+ };
31
+ /**
32
+ * Fiscal regime labels in Spanish for client portal dropdowns
33
+ */
34
+ exports.SAT_CLIENT_FISCAL_REGIME_LABELS = {
35
+ "601": "General de Ley Personas Morales",
36
+ "603": "Personas Morales con Fines no Lucrativos",
37
+ "605": "Sueldos y Salarios e Ingresos Asimilados a Salarios",
38
+ "606": "Arrendamiento",
39
+ "612": "Personas Físicas con Actividades Empresariales y Profesionales",
40
+ "616": "Sin obligaciones fiscales",
41
+ "621": "Incorporación Fiscal",
42
+ "625": "Régimen Simplificado de Confianza (Persona Física)",
43
+ "626": "Régimen Simplificado de Confianza (Persona Moral)",
44
+ };
45
+ /**
46
+ * Fiscal regimes array for dropdowns
47
+ */
48
+ exports.SAT_CLIENT_FISCAL_REGIMES_ARRAY = Object.entries(exports.SAT_CLIENT_FISCAL_REGIME_LABELS).map(([code, label]) => ({
49
+ code: code,
50
+ label: `${code} - ${label}`,
51
+ }));
52
+ // ============================================================================
53
+ // CFDI Use (c_UsoCFDI)
54
+ // ============================================================================
55
+ /**
56
+ * SAT CFDI Use codes applicable to income invoices for veterinary services/products.
57
+ * Subset of the full catalog — only codes relevant to HVP clients.
58
+ */
59
+ exports.SATCfdiUse = {
60
+ GeneralExpenses: "G03",
61
+ MedicalExpenses: "D01",
62
+ NoFiscalEffect: "S01",
63
+ PeriodicPayments: "CP01",
64
+ Acquisitions: "G01",
65
+ };
66
+ /**
67
+ * CFDI Use labels in Spanish for client portal dropdowns
68
+ */
69
+ exports.SAT_CFDI_USE_LABELS = {
70
+ G03: "Gastos en general",
71
+ D01: "Honorarios médicos, dentales y gastos hospitalarios",
72
+ S01: "Sin efectos fiscales",
73
+ CP01: "Pagos",
74
+ G01: "Adquisición de mercancías",
75
+ };
76
+ /**
77
+ * CFDI Use array for dropdowns
78
+ */
79
+ exports.SAT_CFDI_USE_ARRAY = Object.entries(exports.SAT_CFDI_USE_LABELS).map(([code, label]) => ({
80
+ code: code,
81
+ label: `${code} - ${label}`,
82
+ }));
83
+ // ============================================================================
84
+ // Payment Form (c_FormaPago)
85
+ // ============================================================================
86
+ /**
87
+ * SAT Payment Form codes.
88
+ * Maps from QVET payment methods to SAT-compliant codes.
89
+ */
90
+ exports.SATPaymentForm = {
91
+ Cash: "01",
92
+ NominalCheck: "02",
93
+ ElectronicTransfer: "03",
94
+ CreditCard: "04",
95
+ ElectronicWallet: "05",
96
+ ElectronicMoney: "06",
97
+ DigitalVouchers: "08",
98
+ DebitCard: "28",
99
+ ServiceCard: "29",
100
+ ToBeDefined: "99",
101
+ };
102
+ /**
103
+ * Payment form labels in Spanish
104
+ */
105
+ exports.SAT_PAYMENT_FORM_LABELS = {
106
+ "01": "Efectivo",
107
+ "02": "Cheque nominativo",
108
+ "03": "Transferencia electrónica de fondos",
109
+ "04": "Tarjeta de crédito",
110
+ "05": "Monedero electrónico",
111
+ "06": "Dinero electrónico",
112
+ "08": "Vales de despensa",
113
+ "28": "Tarjeta de débito",
114
+ "29": "Tarjeta de servicios",
115
+ "99": "Por definir",
116
+ };
117
+ /**
118
+ * Maps QVET payment method strings to SAT payment form codes.
119
+ * QVET uses Spanish descriptors (UPPERCASE from collections report); SAT uses numeric codes.
120
+ *
121
+ * Source: qvet_collections.paymentMethod actual values (verified from production data).
122
+ */
123
+ exports.QVET_PAYMENT_METHOD_TO_SAT = {
124
+ // Exact matches from QVET collections (report 11) — all uppercase
125
+ EFECTIVO: "01",
126
+ "TARJETA CREDITO": "04",
127
+ "TARJETA DEBITO": "28",
128
+ TRANSFERENCIA: "03",
129
+ "AMERICAN EXPRESS": "04", // AmEx is credit card
130
+ CHEQUE: "02",
131
+ TARJETA: "04", // Generic "card" → credit card
132
+ PUNTOS: "05", // Points → electronic wallet
133
+ "RECIBO DOMICILIADO": "03", // Direct debit → electronic transfer
134
+ // Ignore: RECTIFICADO, VIDEOCONSULTA, FormaPago_MigracionEntregasACuentaAVale → "99"
135
+ };
136
+ /**
137
+ * Default SAT payment form when QVET payment method is unknown
138
+ */
139
+ exports.DEFAULT_SAT_PAYMENT_FORM = "99";
140
+ /**
141
+ * Resolves a QVET payment method string to SAT payment form code.
142
+ * Falls back to "99" (Por definir) if unknown.
143
+ */
144
+ function resolvePaymentForm(qvetPaymentMethod) {
145
+ if (!qvetPaymentMethod)
146
+ return exports.DEFAULT_SAT_PAYMENT_FORM;
147
+ const normalized = qvetPaymentMethod.trim();
148
+ // Direct match (QVET collections uses uppercase)
149
+ if (exports.QVET_PAYMENT_METHOD_TO_SAT[normalized]) {
150
+ return exports.QVET_PAYMENT_METHOD_TO_SAT[normalized];
151
+ }
152
+ // Uppercase match (in case input comes from other source)
153
+ const upper = normalized.toUpperCase();
154
+ if (exports.QVET_PAYMENT_METHOD_TO_SAT[upper]) {
155
+ return exports.QVET_PAYMENT_METHOD_TO_SAT[upper];
156
+ }
157
+ // Case-insensitive partial match as last resort
158
+ const lc = normalized.toLowerCase();
159
+ if (lc.includes("efectivo"))
160
+ return "01";
161
+ if (lc.includes("american") || lc.includes("amex"))
162
+ return "04";
163
+ if (lc.includes("crédito") || lc.includes("credito"))
164
+ return "04";
165
+ if (lc.includes("débito") || lc.includes("debito"))
166
+ return "28";
167
+ if (lc.includes("transferencia"))
168
+ return "03";
169
+ if (lc.includes("cheque"))
170
+ return "02";
171
+ if (lc.includes("tarjeta"))
172
+ return "04";
173
+ return exports.DEFAULT_SAT_PAYMENT_FORM;
174
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const sat_income_invoice_1 = require("./sat-income-invoice");
4
+ describe("resolvePaymentForm", () => {
5
+ describe("exact matches from QVET collections (uppercase)", () => {
6
+ it("should resolve EFECTIVO to 01 (Efectivo)", () => {
7
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("EFECTIVO")).toBe("01");
8
+ });
9
+ it("should resolve TARJETA CREDITO to 04 (Tarjeta de crédito)", () => {
10
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("TARJETA CREDITO")).toBe("04");
11
+ });
12
+ it("should resolve TARJETA DEBITO to 28 (Tarjeta de débito)", () => {
13
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("TARJETA DEBITO")).toBe("28");
14
+ });
15
+ it("should resolve TRANSFERENCIA to 03 (Transferencia electrónica)", () => {
16
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("TRANSFERENCIA")).toBe("03");
17
+ });
18
+ it("should resolve AMERICAN EXPRESS to 04 (Tarjeta de crédito)", () => {
19
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("AMERICAN EXPRESS")).toBe("04");
20
+ });
21
+ it("should resolve CHEQUE to 02 (Cheque nominativo)", () => {
22
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("CHEQUE")).toBe("02");
23
+ });
24
+ it("should resolve TARJETA to 04 (generic card → credit)", () => {
25
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("TARJETA")).toBe("04");
26
+ });
27
+ it("should resolve PUNTOS to 05 (Monedero electrónico)", () => {
28
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("PUNTOS")).toBe("05");
29
+ });
30
+ it("should resolve RECIBO DOMICILIADO to 03 (Transferencia electrónica)", () => {
31
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("RECIBO DOMICILIADO")).toBe("03");
32
+ });
33
+ });
34
+ describe("case-insensitive matching", () => {
35
+ it("should resolve 'Efectivo' (mixed case) to 01", () => {
36
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("Efectivo")).toBe("01");
37
+ });
38
+ it("should resolve 'tarjeta credito' (lowercase) to 04", () => {
39
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("tarjeta credito")).toBe("04");
40
+ });
41
+ it("should resolve 'Tarjeta Debito' (title case) to 28", () => {
42
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("Tarjeta Debito")).toBe("28");
43
+ });
44
+ it("should resolve 'transferencia' (lowercase) to 03", () => {
45
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("transferencia")).toBe("03");
46
+ });
47
+ it("should resolve 'american express' (lowercase) to 04", () => {
48
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("american express")).toBe("04");
49
+ });
50
+ });
51
+ describe("partial matching (fallback)", () => {
52
+ it("should resolve 'Tarjeta de Crédito' (with accents) to 04", () => {
53
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("Tarjeta de Crédito")).toBe("04");
54
+ });
55
+ it("should resolve 'Tarjeta de Débito' (with accents) to 28", () => {
56
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("Tarjeta de Débito")).toBe("28");
57
+ });
58
+ it("should resolve 'Pago en efectivo' to 01", () => {
59
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("Pago en efectivo")).toBe("01");
60
+ });
61
+ it("should resolve 'Transferencia bancaria' to 03", () => {
62
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("Transferencia bancaria")).toBe("03");
63
+ });
64
+ });
65
+ describe("unknown/edge cases → 99 (Por definir)", () => {
66
+ it("should resolve RECTIFICADO to 99", () => {
67
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("RECTIFICADO")).toBe("99");
68
+ });
69
+ it("should resolve VIDEOCONSULTA to 99", () => {
70
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("VIDEOCONSULTA")).toBe("99");
71
+ });
72
+ it("should resolve FormaPago_MigracionEntregasACuentaAVale to 99", () => {
73
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("FormaPago_MigracionEntregasACuentaAVale")).toBe("99");
74
+ });
75
+ it("should resolve empty string to 99", () => {
76
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("")).toBe("99");
77
+ });
78
+ it("should resolve unknown method to 99", () => {
79
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("BITCOIN")).toBe("99");
80
+ });
81
+ });
82
+ describe("whitespace handling", () => {
83
+ it("should trim whitespace", () => {
84
+ expect((0, sat_income_invoice_1.resolvePaymentForm)(" EFECTIVO ")).toBe("01");
85
+ });
86
+ it("should handle extra spaces in method name", () => {
87
+ expect((0, sat_income_invoice_1.resolvePaymentForm)("TARJETA CREDITO")).toBe("04");
88
+ });
89
+ });
90
+ });
@@ -0,0 +1,2 @@
1
+ export * from './requests';
2
+ export * from './responses';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./requests"), exports);
18
+ __exportStar(require("./responses"), exports);
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Client Billing API - Request Types
3
+ *
4
+ * Request types for the client-facing billing portal endpoints.
5
+ *
6
+ * @see /api/client-billing/*
7
+ */
8
+ /**
9
+ * Register a new client account.
10
+ *
11
+ * @example POST /api/client-billing/auth/register
12
+ */
13
+ export interface RegisterClientRequest {
14
+ email: string;
15
+ password: string;
16
+ name: string;
17
+ }
18
+ /**
19
+ * Log in with email and password.
20
+ *
21
+ * @example POST /api/client-billing/auth/login
22
+ */
23
+ export interface LoginClientRequest {
24
+ email: string;
25
+ password: string;
26
+ }
27
+ /**
28
+ * Update client fiscal profile data.
29
+ * All fields optional — only provided fields are updated.
30
+ *
31
+ * @example PATCH /api/client-billing/profile
32
+ */
33
+ export interface UpdateClientProfileRequest {
34
+ name?: string;
35
+ rfc?: string;
36
+ businessName?: string;
37
+ fiscalRegime?: string;
38
+ postalCode?: string;
39
+ cfdiUse?: string;
40
+ }
41
+ /**
42
+ * Look up a ticket by invoice number (e.g. "H-4543") and amount for verification.
43
+ * Amount is required as security measure (prevents facturing others' tickets).
44
+ * Accepts variants: "H4543", "H-4543", "h-4543", "h 4543".
45
+ *
46
+ * @example POST /api/client-billing/invoices/lookup
47
+ */
48
+ export interface LookupTicketRequest {
49
+ invoiceNumber: string;
50
+ amount: number;
51
+ }
52
+ /**
53
+ * Request an invoice to be generated for a ticket.
54
+ * Uses fiscal data from the client's saved profile.
55
+ *
56
+ * @example POST /api/client-billing/invoices
57
+ */
58
+ export interface CreateClientInvoiceRequest {
59
+ invoiceNumber: string;
60
+ amount: number;
61
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * Client Billing API - Request Types
4
+ *
5
+ * Request types for the client-facing billing portal endpoints.
6
+ *
7
+ * @see /api/client-billing/*
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Client Billing API - Response Types
3
+ *
4
+ * Response types for the client-facing billing portal endpoints.
5
+ *
6
+ * @see /api/client-billing/*
7
+ */
8
+ import { ClientInvoiceStatus } from '../../constants/client-billing.enums';
9
+ /**
10
+ * Client account data returned after login/register.
11
+ *
12
+ * @example POST /api/client-billing/auth/login
13
+ */
14
+ export interface ClientAuthResponse {
15
+ token: string;
16
+ client: ClientProfileResponse;
17
+ }
18
+ /**
19
+ * Client profile with fiscal data.
20
+ *
21
+ * @example GET /api/client-billing/profile
22
+ */
23
+ export interface ClientProfileResponse {
24
+ id: string;
25
+ email: string;
26
+ name: string;
27
+ rfc?: string;
28
+ businessName?: string;
29
+ fiscalRegime?: string;
30
+ postalCode?: string;
31
+ cfdiUse?: string;
32
+ isProfileComplete: boolean;
33
+ createdAt: string;
34
+ }
35
+ /**
36
+ * Single line item within a ticket lookup or invoice.
37
+ */
38
+ export interface InvoiceLineItemResponse {
39
+ productName: string;
40
+ quantity: number;
41
+ unitPrice: number;
42
+ discount: number;
43
+ taxRate: number;
44
+ taxAmount: number;
45
+ total: number;
46
+ satProductCode?: string;
47
+ satUnitCode?: string;
48
+ }
49
+ /**
50
+ * Result of looking up a ticket by invoice number (e.g. "H-4543", "U-5434").
51
+ * Returned before the client confirms invoice creation.
52
+ *
53
+ * @example POST /api/client-billing/invoices/lookup
54
+ */
55
+ export interface TicketLookupResponse {
56
+ invoiceNumber: string;
57
+ /** @deprecated Use invoiceNumber instead */
58
+ deliveryNoteNumber: number;
59
+ date: string;
60
+ customerName: string;
61
+ subtotal: number;
62
+ taxTotal: number;
63
+ total: number;
64
+ paymentMethod: string;
65
+ lineItems: InvoiceLineItemResponse[];
66
+ }
67
+ /**
68
+ * Client invoice summary for list views.
69
+ *
70
+ * @example GET /api/client-billing/invoices
71
+ */
72
+ export interface ClientInvoiceListItemResponse {
73
+ id: string;
74
+ invoiceNumber: string;
75
+ date: string;
76
+ total: number;
77
+ status: ClientInvoiceStatus;
78
+ cfdiUuid?: string;
79
+ createdAt: string;
80
+ }
81
+ /**
82
+ * Full client invoice detail.
83
+ *
84
+ * @example GET /api/client-billing/invoices/:id
85
+ */
86
+ export interface ClientInvoiceDetailResponse {
87
+ id: string;
88
+ invoiceNumber: string;
89
+ date: string;
90
+ customerName: string;
91
+ subtotal: number;
92
+ taxTotal: number;
93
+ total: number;
94
+ paymentMethod: string;
95
+ status: ClientInvoiceStatus;
96
+ cfdiUuid?: string;
97
+ facturamaId?: string;
98
+ errorMessage?: string;
99
+ lineItems: InvoiceLineItemResponse[];
100
+ createdAt: string;
101
+ updatedAt: string;
102
+ }
103
+ /**
104
+ * Processing status for polling during invoice generation.
105
+ *
106
+ * @example GET /api/client-billing/invoices/:id/status
107
+ */
108
+ export interface ClientInvoiceStatusResponse {
109
+ id: string;
110
+ status: ClientInvoiceStatus;
111
+ progress?: number;
112
+ message?: string;
113
+ errorMessage?: string;
114
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * Client Billing API - Response Types
4
+ *
5
+ * Response types for the client-facing billing portal endpoints.
6
+ *
7
+ * @see /api/client-billing/*
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -12,3 +12,4 @@ export * from './cash-reconciliation';
12
12
  export * from './time-off-request';
13
13
  export * from './job';
14
14
  export * from './inventory-session';
15
+ export * from './client-billing';
@@ -28,3 +28,4 @@ __exportStar(require("./cash-reconciliation"), exports);
28
28
  __exportStar(require("./time-off-request"), exports);
29
29
  __exportStar(require("./job"), exports);
30
30
  __exportStar(require("./inventory-session"), exports);
31
+ __exportStar(require("./client-billing"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hvp-shared",
3
- "version": "6.84.0",
3
+ "version": "6.86.0",
4
4
  "description": "Shared types and utilities for HVP backend and frontend",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",