hvp-shared 6.85.0 → 6.87.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.
@@ -15,7 +15,22 @@ export declare enum ClientInvoiceStatus {
15
15
  /** CFDI stamped successfully, PDF/XML available */
16
16
  stamped = "stamped",
17
17
  /** Processing failed (see errorMessage) */
18
- failed = "failed"
18
+ failed = "failed",
19
+ /** Previous month invoice — requires admin/manager authorization */
20
+ requires_authorization = "requires_authorization",
21
+ /** CFDI cancelled with SAT */
22
+ cancelled = "cancelled"
23
+ }
24
+ /**
25
+ * Date rule applied to an invoice based on ticket date vs emission date.
26
+ */
27
+ export declare enum InvoiceDateRule {
28
+ /** Ticket date within 72h — stamp with original date */
29
+ within_72h = "within_72h",
30
+ /** Ticket date >72h ago, same fiscal month — stamp with today's date */
31
+ same_month = "same_month",
32
+ /** Ticket date >72h ago, previous fiscal month — requires authorization */
33
+ previous_month = "previous_month"
19
34
  }
20
35
  /**
21
36
  * All ClientInvoiceStatus values as array (for dropdowns/filters)
@@ -25,3 +40,10 @@ export declare const CLIENT_INVOICE_STATUS_VALUES: ClientInvoiceStatus[];
25
40
  * ClientInvoiceStatus labels in Spanish (for UI)
26
41
  */
27
42
  export declare const CLIENT_INVOICE_STATUS_LABELS: Record<ClientInvoiceStatus, string>;
43
+ /**
44
+ * Petco (MASCOTAS Y COMPAÑIA) — different invoice email per branch.
45
+ * Only case that requires branch-specific emails.
46
+ */
47
+ export declare const PETCO_RFC = "MAS121116E51";
48
+ export declare const PETCO_BRANCH_EMAILS: Record<string, string>;
49
+ export declare const INVOICE_DATE_RULE_LABELS: Record<InvoiceDateRule, string>;
@@ -6,7 +6,7 @@
6
6
  * request CFDI income invoices for their veterinary visits.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.CLIENT_INVOICE_STATUS_LABELS = exports.CLIENT_INVOICE_STATUS_VALUES = exports.ClientInvoiceStatus = void 0;
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
10
  /**
11
11
  * Status of a client invoice request through the processing pipeline.
12
12
  */
@@ -20,7 +20,23 @@ var ClientInvoiceStatus;
20
20
  ClientInvoiceStatus["stamped"] = "stamped";
21
21
  /** Processing failed (see errorMessage) */
22
22
  ClientInvoiceStatus["failed"] = "failed";
23
+ /** Previous month invoice — requires admin/manager authorization */
24
+ ClientInvoiceStatus["requires_authorization"] = "requires_authorization";
25
+ /** CFDI cancelled with SAT */
26
+ ClientInvoiceStatus["cancelled"] = "cancelled";
23
27
  })(ClientInvoiceStatus || (exports.ClientInvoiceStatus = ClientInvoiceStatus = {}));
28
+ /**
29
+ * Date rule applied to an invoice based on ticket date vs emission date.
30
+ */
31
+ var InvoiceDateRule;
32
+ (function (InvoiceDateRule) {
33
+ /** Ticket date within 72h — stamp with original date */
34
+ InvoiceDateRule["within_72h"] = "within_72h";
35
+ /** Ticket date >72h ago, same fiscal month — stamp with today's date */
36
+ InvoiceDateRule["same_month"] = "same_month";
37
+ /** Ticket date >72h ago, previous fiscal month — requires authorization */
38
+ InvoiceDateRule["previous_month"] = "previous_month";
39
+ })(InvoiceDateRule || (exports.InvoiceDateRule = InvoiceDateRule = {}));
24
40
  /**
25
41
  * All ClientInvoiceStatus values as array (for dropdowns/filters)
26
42
  */
@@ -33,4 +49,21 @@ exports.CLIENT_INVOICE_STATUS_LABELS = {
33
49
  [ClientInvoiceStatus.processing]: "Procesando",
34
50
  [ClientInvoiceStatus.stamped]: "Facturada",
35
51
  [ClientInvoiceStatus.failed]: "Error",
52
+ [ClientInvoiceStatus.requires_authorization]: "Requiere autorización",
53
+ [ClientInvoiceStatus.cancelled]: "Cancelada",
54
+ };
55
+ /**
56
+ * Petco (MASCOTAS Y COMPAÑIA) — different invoice email per branch.
57
+ * Only case that requires branch-specific emails.
58
+ */
59
+ exports.PETCO_RFC = "MAS121116E51";
60
+ exports.PETCO_BRANCH_EMAILS = {
61
+ URBAN: "7132ger@petco.com.mx",
62
+ HARBOR: "7178ger@petco.com.mx",
63
+ MONTEJO: "7154ger@petco.com.mx",
64
+ };
65
+ exports.INVOICE_DATE_RULE_LABELS = {
66
+ [InvoiceDateRule.within_72h]: "Dentro de 72 horas",
67
+ [InvoiceDateRule.same_month]: "Mismo mes (>72h)",
68
+ [InvoiceDateRule.previous_month]: "Mes anterior",
36
69
  };
@@ -79,9 +79,9 @@ export type SATPaymentFormCode = (typeof SATPaymentForm)[keyof typeof SATPayment
79
79
  export declare const SAT_PAYMENT_FORM_LABELS: Record<SATPaymentFormCode, string>;
80
80
  /**
81
81
  * Maps QVET payment method strings to SAT payment form codes.
82
- * QVET uses Spanish descriptors; SAT uses numeric codes.
82
+ * QVET uses Spanish descriptors (UPPERCASE from collections report); SAT uses numeric codes.
83
83
  *
84
- * TODO: Validate actual QVET payment method strings from qvet_collection_details data.
84
+ * Source: qvet_collections.paymentMethod actual values (verified from production data).
85
85
  */
86
86
  export declare const QVET_PAYMENT_METHOD_TO_SAT: Record<string, SATPaymentFormCode>;
87
87
  /**
@@ -116,17 +116,22 @@ exports.SAT_PAYMENT_FORM_LABELS = {
116
116
  };
117
117
  /**
118
118
  * Maps QVET payment method strings to SAT payment form codes.
119
- * QVET uses Spanish descriptors; SAT uses numeric codes.
119
+ * QVET uses Spanish descriptors (UPPERCASE from collections report); SAT uses numeric codes.
120
120
  *
121
- * TODO: Validate actual QVET payment method strings from qvet_collection_details data.
121
+ * Source: qvet_collections.paymentMethod actual values (verified from production data).
122
122
  */
123
123
  exports.QVET_PAYMENT_METHOD_TO_SAT = {
124
- Efectivo: "01",
125
- "Tarjeta de Crédito": "04",
126
- "Tarjeta de Débito": "28",
127
- Transferencia: "03",
128
- "Tarjeta crédito": "04",
129
- "Tarjeta débito": "28",
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"
130
135
  };
131
136
  /**
132
137
  * Default SAT payment form when QVET payment method is unknown
@@ -140,14 +145,21 @@ function resolvePaymentForm(qvetPaymentMethod) {
140
145
  if (!qvetPaymentMethod)
141
146
  return exports.DEFAULT_SAT_PAYMENT_FORM;
142
147
  const normalized = qvetPaymentMethod.trim();
143
- // Direct match
148
+ // Direct match (QVET collections uses uppercase)
144
149
  if (exports.QVET_PAYMENT_METHOD_TO_SAT[normalized]) {
145
150
  return exports.QVET_PAYMENT_METHOD_TO_SAT[normalized];
146
151
  }
147
- // Case-insensitive partial match
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
148
158
  const lc = normalized.toLowerCase();
149
159
  if (lc.includes("efectivo"))
150
160
  return "01";
161
+ if (lc.includes("american") || lc.includes("amex"))
162
+ return "04";
151
163
  if (lc.includes("crédito") || lc.includes("credito"))
152
164
  return "04";
153
165
  if (lc.includes("débito") || lc.includes("debito"))
@@ -156,5 +168,7 @@ function resolvePaymentForm(qvetPaymentMethod) {
156
168
  return "03";
157
169
  if (lc.includes("cheque"))
158
170
  return "02";
171
+ if (lc.includes("tarjeta"))
172
+ return "04";
159
173
  return exports.DEFAULT_SAT_PAYMENT_FORM;
160
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
+ });
@@ -39,13 +39,14 @@ export interface UpdateClientProfileRequest {
39
39
  cfdiUse?: string;
40
40
  }
41
41
  /**
42
- * Look up a ticket by albarán number and amount for verification.
42
+ * Look up a ticket by invoice number (e.g. "H-4543") and amount for verification.
43
43
  * Amount is required as security measure (prevents facturing others' tickets).
44
+ * Accepts variants: "H4543", "H-4543", "h-4543", "h 4543".
44
45
  *
45
46
  * @example POST /api/client-billing/invoices/lookup
46
47
  */
47
48
  export interface LookupTicketRequest {
48
- deliveryNoteNumber: number;
49
+ invoiceNumber: string;
49
50
  amount: number;
50
51
  }
51
52
  /**
@@ -55,6 +56,6 @@ export interface LookupTicketRequest {
55
56
  * @example POST /api/client-billing/invoices
56
57
  */
57
58
  export interface CreateClientInvoiceRequest {
58
- deliveryNoteNumber: number;
59
+ invoiceNumber: string;
59
60
  amount: number;
60
61
  }
@@ -47,12 +47,14 @@ export interface InvoiceLineItemResponse {
47
47
  satUnitCode?: string;
48
48
  }
49
49
  /**
50
- * Result of looking up a ticket by albarán number.
50
+ * Result of looking up a ticket by invoice number (e.g. "H-4543", "U-5434").
51
51
  * Returned before the client confirms invoice creation.
52
52
  *
53
53
  * @example POST /api/client-billing/invoices/lookup
54
54
  */
55
55
  export interface TicketLookupResponse {
56
+ invoiceNumber: string;
57
+ /** @deprecated Use invoiceNumber instead */
56
58
  deliveryNoteNumber: number;
57
59
  date: string;
58
60
  customerName: string;
@@ -69,7 +71,7 @@ export interface TicketLookupResponse {
69
71
  */
70
72
  export interface ClientInvoiceListItemResponse {
71
73
  id: string;
72
- deliveryNoteNumber: number;
74
+ invoiceNumber: string;
73
75
  date: string;
74
76
  total: number;
75
77
  status: ClientInvoiceStatus;
@@ -83,7 +85,7 @@ export interface ClientInvoiceListItemResponse {
83
85
  */
84
86
  export interface ClientInvoiceDetailResponse {
85
87
  id: string;
86
- deliveryNoteNumber: number;
88
+ invoiceNumber: string;
87
89
  date: string;
88
90
  customerName: string;
89
91
  subtotal: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hvp-shared",
3
- "version": "6.85.0",
3
+ "version": "6.87.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",