Skip to content

Commit 44dabbf

Browse files
committed
products tested
1 parent 8afc809 commit 44dabbf

5 files changed

Lines changed: 124 additions & 230 deletions

File tree

examples/main.ts

Lines changed: 68 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,83 @@
1-
import { FiscalapiClient, FiscalapiSettings } from '../src';
1+
import { FiscalapiClient, FiscalapiSettings, Product } from '../src';
2+
import { inspect } from 'util';
3+
inspect.defaultOptions.depth = null; // Deshabilitar la profundidad de inspección para objetos anidados la salida de la consola
4+
inspect.defaultOptions.colors = true; // Habilitar colores para la salida de la consola
25

36
async function main() : Promise<void> {
4-
5-
// Configura el cliente
7+
8+
// Configura el cliente de FiscalAPI
69
const settings: FiscalapiSettings = {
710
apiUrl: 'https://localhost:7173',
811
apiKey: 'sk_development_e0e47dfa_5146_40c2_b3a3_3055909a6b88',
912
tenant: 'e839651d-1765-4cd0-ba7f-547a4c20580f',
1013
};
1114

15+
// Sellos SAT CSD del emisor para emisión de CFDI
16+
const base64Cert = `MIIFgDCCA2igAwIBAgIUMzAwMDEwMDAwMDA1MDAwMDM0NDYwDQYJKoZIhvcNAQELBQAwggErMQ8wDQYDVQQDDAZBQyBVQVQxLjAsBgNVBAoMJVNFUlZJQ0lPIERFIEFETUlOSVNUUkFDSU9OIFRSSUJVVEFSSUExGjAYBgNVBAsMEVNBVC1JRVMgQXV0aG9yaXR5MSgwJgYJKoZIhvcNAQkBFhlvc2Nhci5tYXJ0aW5lekBzYXQuZ29iLm14MR0wGwYDVQQJDBQzcmEgY2VycmFkYSBkZSBjYWxpejEOMAwGA1UEEQwFMDYzNzAxCzAJBgNVBAYTAk1YMRkwFwYDVQQIDBBDSVVEQUQgREUgTUVYSUNPMREwDwYDVQQHDAhDT1lPQUNBTjERMA8GA1UELRMIMi41LjQuNDUxJTAjBgkqhkiG9w0BCQITFnJlc3BvbnNhYmxlOiBBQ0RNQS1TQVQwHhcNMjMwNTE4MTQzNTM3WhcNMjcwNTE4MTQzNTM3WjCBpzEdMBsGA1UEAxMUS0FSTEEgRlVFTlRFIE5PTEFTQ08xHTAbBgNVBCkTFEtBUkxBIEZVRU5URSBOT0xBU0NPMR0wGwYDVQQKExRLQVJMQSBGVUVOVEUgTk9MQVNDTzEWMBQGA1UELRMNRlVOSzY3MTIyOFBINjEbMBkGA1UEBRMSRlVOSzY3MTIyOE1DTE5MUjA1MRMwEQYDVQQLEwpTdWN1cnNhbCAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhNXbTSqGX6+/3Urpemyy5vVG2IdP2v7v001+c4BoMxEDFDQ32cOFdDiRxy0Fq9aR+Ojrofq8VeftvN586iyA1A6a0QnA68i7JnQKI4uJy+u0qiixuHu6u3b3BhSpoaVHcUtqFWLLlzr0yBxfVLOqVna/1/tHbQJg9hx57mp97P0JmXO1WeIqi+Zqob/mVZh2lsPGdJ8iqgjYFaFn9QVOQ1Pq74o1PTqwfzqgJSfV0zOOlESDPWggaDAYE4VNyTBisOUjlNd0x7ppcTxSi3yenrJHqkq/pqJsRLKf6VJ/s9p6bsd2bj07hSDpjlDC2lB25eEfkEkeMkXoE7ErXQ5QCwIDAQABox0wGzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQsFAAOCAgEAHwYpgbClHULXYhK4GNTgonvXh81oqfXwCSWAyDPiTYFDWVfWM9C4ApxMLyc0XvJte75Rla+bPC08oYN3OlhbbvP3twBL/w9SsfxvkbpFn2ZfGSTXZhyiq4vjmQHW1pnFvGelwgU4v3eeRE/MjoCnE7M/Q5thpuog6WGf7CbKERnWZn8QsUaJsZSEkg6Bv2jm69ye57ab5rrOUaeMlstTfdlaHAEkUgLX/NXq7RbGwv82hkHY5b2vYcXeh34tUMBL6os3OdRlooN9ZQGkVIISvxVZpSHkYC20DFNh1Bb0ovjfujlTcka81GnbUhFGZtRuoVQ1RVpMO8xtx3YKBLp4do3hPmnRCV5hCm43OIjYx9Ov2dqICV3AaNXSLV1dW39Bak/RBiIDGHzOIW2+VMPjvvypBjmPv/tmbqNHWPSAWOxTyMx6E1gFCZvi+5F+BgkdC3Lm7U0BU0NfvsXajZd8sXnIllvEMrikCLoI/yurvexNDcF1RW/FhMsoua0eerwczcNm66pGjHm05p9DR6lFeJZrtqeqZuojdxBWy4vH6ghyJaupergoX+nmdG3JYeRttCFF/ITI68TeCES5V3Y0C3psYAg1XxcGRLGd4chPo/4xwiLkijWtgt0/to5ljGBwfK7r62PHZfL1Dp+i7V3w7hmOlhbXzP+zhMZn1GCk7KY=`; // Reemplaza con tu certificado en base64
17+
const base64Key = `MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIAgEAAoIBAQACAggAMBQGCCqGSIb3DQMHBAgwggS9AgEAMASCBMh4EHl7aNSCaMDA1VlRoXCZ5UUmqErAbucRBAKNQXH8t8gVCl/ItHMI2hMJ76QOECOqEi1Y89cDpegDvh/INXyMsXbzi87tfFzgq1O+9ID6aPWGg+bNGADXyXxDVdy7Nq/SCdoXvo66MTYwq8jyJeUHDHEGMVBcmZpD44VJCvLBxDcvByuevP4Wo2NKqJCwK+ecAdZc/8Rvd947SjbMHuS8BppfQWARVUqA5BLOkTAHNv6tEk/hncC7O2YOGSShart8fM8dokgGSyewHVFe08POuQ+WDHeVpvApH/SP29rwktSoiHRoL6dK+F2YeEB5SuFW9LQgYCutjapmUP/9TC3Byro9Li6UrvQHxNmgMFGQJSYjFdqlGjLibfuguLp7pueutbROoZaSxU8HqlfYxLkpJUxUwNI1ja/1t3wcivtWknVXBd13R06iVfU1HGe8Kb4u5il4a4yP4p7VT4RE3b1SBLJeG+BxHiE8gFaaKcX/Cl6JV14RPTvk/6VnAtEQ66qHJex21KKuiJo2JoOmDXVHmvGQlWXNjYgoPx28Xd5WsofL+n7HDR2Ku8XgwJw6IXBJGuoday9qWN9v/k7DGlNGB6Sm4gdVUmycMP6EGhB1vFTiDfOGQO42ywmcpKoMETPVQ5InYKE0xAOckgcminDgxWjtUHjBDPEKifEjYudPwKmR6Cf4ZdGvUWwY/zq9pPAC9bu423KeBCnSL8AQ4r5SVsW6XG0njamwfNjpegwh/YG7sS7sDtZ8gi7r6tZYjsOqZlCYU0j7QTBpuQn81Yof2nQRCFxhRJCeydmIA8+z0nXrcElk7NDPk4kYQS0VitJ2qeQYNENzGBglROkCl2y6GlxAG80IBtReCUp/xOSdlwDR0eim+SNkdStvmQM5IcWBuDKwGZc1A4v/UoLl7niV9fpl4X6bUX8lZzY4gidJOafoJ30VoY/lYGkrkEuz3GpbbT5v8fF3iXVRlEqhlpe8JSGu7Rd2cPcJSkQ1Cuj/QRhHPhFMF2KhTEf95c9ZBKI8H7SvBi7eLXfSW2Y0ve6vXBZKyjK9whgCU9iVOsJjqRXpAccaWOKi420CjmS0+uwj/Xr2wLZhPEjBA/G6Od30+eG9mICmbp/5wAGhK/ZxCT17ZETyFmOMo49jl9pxdKocJNuzMrLpSz7/g5Jwp8+y8Ck5YP7AX0R/dVA0t37DO7nAbQT5XVSYpMVh/yvpYJ9WR+tb8Yg1h2lERLR2fbuhQRcwmisZR2W3Sr2b7hX9MCMkMQw8y2fDJrzLrqKqkHcjvnI/TdzZW2MzeQDoBBb3fmgvjYg07l4kThS73wGX992w2Y+a1A2iirSmrYEm9dSh16JmXa8boGQAONQzQkHh7vpw0IBs9cnvqO1QLB1GtbBztUBXonA4TxMKLYZkVrrd2RhrYWMsDp7MpC4M0p/DA3E/qscYwq1OpwriewNdx6XXqMZbdUNqMP2viBY2VSGmNdHtVfbN/rnaeJetFGX7XgTVYD7wDq8TW9yseCK944jcT+y/o0YiT9j3OLQ2Ts0LDTQskpJSxRmXEQGy3NBDOYFTvRkcGJEQJItuol8NivJN1H9LoLIUAlAHBZxfHpUYx66YnP4PdTdMIWH+nxyekKPFfAT7olQ=`; // Reemplaza con tu clave privada en base64
18+
const password = '12345678a'; // Reemplaza con la contraseña de tu clave privada
19+
1220
try {
21+
console.log('Hello Fiscalapi node...');
22+
1323
// Crea el cliente
14-
console.log('Inicializando cliente de FiscalAPI...');
1524
const client = FiscalapiClient.create(settings);
16-
17-
// Ejemplo: Listar productos (página 1, 10 elementos por página)
18-
console.log('Obteniendo producto...');
19-
const response = await client.products.getById("114a4be5-fb65-40b2-a762-ff0c55c6ebfa",true);
20-
21-
if (response.succeeded) {
22-
23-
console.log('Exito');
24-
console.log(JSON.stringify(response.data, null, 2));
25-
26-
} else {
27-
console.log('Error');
28-
console.log(JSON.stringify(response.data, null, 2));
29-
}
30-
} catch (error) {
31-
console.error('Error inesperado:', error);
32-
25+
26+
// Listar productos
27+
// const apiResponse = await client.products.getList(1, 2);
28+
// console.log('apiResponse:', apiResponse);
29+
30+
// Obtiene producto por ID
31+
// const apiResponse = await client.products.getById("114a4be5-fb65-40b2-a762-ff0c55c6ebfa",true);
32+
// console.log('apiResponse:', apiResponse);
33+
34+
// Crear producto
35+
// const modelRequest: Product = {
36+
// description: 'Libro de JavaScript',
37+
// unitPrice: 200,
38+
// }
39+
// const apiResponse = await client.products.create(modelRequest);
40+
// console.log('apiResponse:', apiResponse);
41+
42+
// Actualizar producto
43+
// const modelRequest: Product = {
44+
// id: 'cf792d75-7c81-446c-be28-f098f9cb601a',
45+
// description: 'Libro de JavaScript actualizado',
46+
// unitPrice: 250,
47+
// satUnitMeasurementId: 'D63',
48+
// satTaxObjectId: '01',
49+
// satProductCodeId: '14111804',
50+
// productTaxes: [
51+
// {
52+
// rate: 0.16, // Tasa del impuesto. El valor debe estar entre 0.00000 y 1.000000 p. ej. `0.160000` para un 16% de impuesto
53+
// taxId: '002', // 001=ISR, 002=IVA, 003=IEPS
54+
// taxFlagId: 'T', // T=Traslado o R=Retención
55+
// taxTypeId: 'Tasa', // Tasa, Cuota o Exento
56+
// },
57+
// {
58+
// rate: 0.08, // Tasa del impuesto
59+
// taxId: '003', // 001=ISR, 002=IVA, 003=IEPS
60+
// taxFlagId: 'T', // T=Traslado o R=Retención
61+
// taxTypeId: 'Tasa', // Tasa, Cuota o Exento
62+
// }
63+
// ]
64+
// };
65+
// const apiResponse = await client.products.update("cf792d75-7c81-446c-be28-f098f9cb601a", modelRequest);
66+
// console.log('apiResponse:', apiResponse);
67+
68+
69+
// Eliminar producto
70+
// const apiResponse = await client.products.delete("cf792d75-7c81-446c-be28-f098f9cb601a");
71+
// console.log('apiResponse:', apiResponse);
72+
73+
74+
console.log('End Fiscalapi node...');
75+
} catch (error: unknown) {
76+
console.error('Error inesperado:', error);
3377
}
3478
}
3579

3680
// Ejecutar la función principal
37-
main().catch(console.error);
81+
main().catch(console.error);
82+
83+

src/common/base-dto.ts

Lines changed: 0 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -6,176 +6,4 @@ import { AuditableDto } from "./auditable-dto";
66
*/
77
export class BaseDto extends AuditableDto {
88
id?: string;
9-
10-
/**
11-
* Sobrescribe el método toJSON para:
12-
* 1. Formatear automáticamente propiedades DateTime de Luxon
13-
* 2. Excluir propiedades falsy (null, undefined, '', 0, false)
14-
* 3. Manejar recursivamente objetos anidados y arrays
15-
* 4. Manejar edge cases como referencias circulares, valores especiales, etc.
16-
* @param {string} dateFormat - Formato de fecha (por defecto ISO)
17-
* @param {boolean} excludeFalsy - Si se deben excluir valores falsy
18-
* @returns {Object} - Objeto JSON limpio
19-
*/
20-
toJSON(dateFormat = "yyyy-MM-dd'T'HH:mm:ss", excludeFalsy = true) {
21-
// Set para detectar referencias circulares
22-
const visited = new WeakSet();
23-
24-
const processValue = (value:any):any => {
25-
// Si es null o undefined
26-
if (value === null || value === undefined) {
27-
return excludeFalsy ? undefined : null;
28-
}
29-
30-
// Si es un DateTime de Luxon
31-
if (value instanceof DateTime) {
32-
// Verificar si es válido
33-
if (!value.isValid) {
34-
return excludeFalsy ? undefined : null;
35-
}
36-
return value.toFormat(dateFormat);
37-
}
38-
39-
// Si es un array
40-
if (Array.isArray(value)) {
41-
// Procesamos cada elemento y filtramos valores undefined si excludeFalsy es true
42-
const processedArray = value
43-
.map(item => processValue(item))
44-
.filter(item => !excludeFalsy || item !== undefined);
45-
46-
// Devolvemos array vacío o undefined según configuración
47-
return processedArray.length > 0 ? processedArray : (excludeFalsy ? undefined : []);
48-
}
49-
50-
// Si es un objeto (pero no Date nativa)
51-
if (typeof value === 'object' && value !== null && !(value instanceof Date)) {
52-
return processObject(value);
53-
}
54-
55-
// Si es una instancia de Date nativa
56-
if (value instanceof Date) {
57-
return DateTime.fromJSDate(value).toFormat(dateFormat);
58-
}
59-
60-
// Para valores especiales de JavaScript (NaN, Infinity, -Infinity)
61-
if (typeof value === 'number' && !isFinite(value)) {
62-
return excludeFalsy ? undefined : null;
63-
}
64-
65-
// Para funciones (siempre las excluimos)
66-
if (typeof value === 'function') {
67-
return undefined;
68-
}
69-
70-
// Para BigInt (convertir a string)
71-
if (typeof value === 'bigint') {
72-
return value.toString();
73-
}
74-
75-
// Para Symbol (convertir a string descriptiva)
76-
if (typeof value === 'symbol') {
77-
return value.toString();
78-
}
79-
80-
// Para strings vacíos, números 0 y booleanos false
81-
if (excludeFalsy && (value === '' || value === 0 || value === false)) {
82-
return undefined;
83-
}
84-
85-
// Cualquier otro valor lo devolvemos tal cual
86-
return value;
87-
};
88-
89-
const processObject = (obj:any) => {
90-
// Verificar objeto nulo o undefined
91-
if (!obj) return excludeFalsy ? undefined : null;
92-
93-
// Detectar referencias circulares
94-
if (visited.has(obj)) {
95-
return "[Referencia Circular]";
96-
}
97-
98-
// Agregamos el objeto al conjunto de visitados
99-
visited.add(obj);
100-
101-
// Manejar Map
102-
if (obj instanceof Map) {
103-
const entries = Array.from(obj.entries()).map(([k, v]) => {
104-
return { key: String(k), value: processValue(v) };
105-
}).filter(entry => !excludeFalsy || entry.value !== undefined);
106-
107-
return entries.length > 0 ? entries : (excludeFalsy ? undefined : []);
108-
}
109-
110-
// Manejar Set
111-
if (obj instanceof Set) {
112-
const values = Array.from(obj.values())
113-
.map(v => processValue(v))
114-
.filter(value => !excludeFalsy || value !== undefined);
115-
116-
return values.length > 0 ? values : (excludeFalsy ? undefined : []);
117-
}
118-
119-
// Si el objeto tiene su propio método toJSON, lo usamos
120-
// pero pasamos nuestros parámetros si la función los acepta
121-
if (obj !== this && typeof obj.toJSON === 'function') {
122-
try {
123-
const paramCount = obj.toJSON.length;
124-
if (paramCount >= 2) {
125-
return obj.toJSON(dateFormat, excludeFalsy);
126-
} else if (paramCount === 1) {
127-
return obj.toJSON(dateFormat);
128-
} else {
129-
return obj.toJSON();
130-
}
131-
} catch (error) {
132-
if (error instanceof Error) {
133-
console.warn(`Error en método toJSON personalizado: ${error.message}`);
134-
} else {
135-
console.warn('Error en método toJSON personalizado: Error desconocido');
136-
}
137-
// Continuamos con el procesamiento normal si falla el método toJSON
138-
}
139-
}
140-
141-
const result: Record<string, any> = {};
142-
let hasValues = false;
143-
144-
// Iteramos sobre todas las propiedades (solo las propias)
145-
for (const key in obj) {
146-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
147-
try {
148-
const processed = processValue(obj[key]);
149-
150-
if (!excludeFalsy || processed !== undefined) {
151-
result[key] = processed;
152-
hasValues = true;
153-
}
154-
} catch (error) {
155-
// Si hay un error al procesar un valor, lo omitimos y continuamos
156-
if (error instanceof Error) {
157-
console.warn(`Error al procesar la propiedad "${key}": ${error.message}`);
158-
} else {
159-
console.warn(`Error al procesar la propiedad "${key}": Error desconocido`);
160-
}
161-
}
162-
}
163-
}
164-
165-
return hasValues ? result : (excludeFalsy ? undefined : {});
166-
};
167-
168-
try {
169-
// Procesamos el objeto actual
170-
return processObject(this);
171-
} catch (error) {
172-
if (error instanceof Error) {
173-
console.error(`Error global en toJSON: ${error.message}`);
174-
} else {
175-
console.error('Error global en toJSON: Error desconocido');
176-
}
177-
// En caso de error global, devolvemos un objeto vacío o alguna información de error
178-
return excludeFalsy ? undefined : { error: 'Error en serialización' };
179-
}
180-
}
1819
}

src/common/catalog-dto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { BaseDto } from "./base-dto";
44
export class CatalogDto extends BaseDto {
55
/**
66
* Catalog description
7-
* @example "Catalog for all products"
7+
* @example "Catalogo de formas de pago"
88
*/
99
description?: string;
1010
}

0 commit comments

Comments
 (0)