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.
- package/dist/constants/client-billing.enums.d.ts +47 -0
- package/dist/constants/client-billing.enums.js +66 -0
- package/dist/constants/index.d.ts +2 -0
- package/dist/constants/index.js +2 -0
- package/dist/constants/sat-income-invoice.d.ts +95 -0
- package/dist/constants/sat-income-invoice.js +174 -0
- package/dist/constants/sat-income-invoice.test.d.ts +1 -0
- package/dist/constants/sat-income-invoice.test.js +90 -0
- package/dist/contracts/client-billing/index.d.ts +2 -0
- package/dist/contracts/client-billing/index.js +18 -0
- package/dist/contracts/client-billing/requests.d.ts +61 -0
- package/dist/contracts/client-billing/requests.js +9 -0
- package/dist/contracts/client-billing/responses.d.ts +114 -0
- package/dist/contracts/client-billing/responses.js +9 -0
- package/dist/contracts/index.d.ts +1 -0
- package/dist/contracts/index.js +1 -0
- package/package.json +1 -1
|
@@ -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
|
+
};
|
package/dist/constants/index.js
CHANGED
|
@@ -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,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,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
|
+
}
|
package/dist/contracts/index.js
CHANGED