Commit f1a1cc95984cfcf6f39fc7a786656f2e15adab46

Authored by Eric Fernandez
1 parent 585772b1bb
Exists in master

primera versión estable

debo/cabeceraDebo.js
1 module.exports = function(comprobante, afipTablas, entities) { 1 module.exports = function(comprobante, afipTablas, entities) {
2 2
3 return { 3 return {
4 TIP: afipTablas(comprobante.identificaxComprobante.tipo).letraComprobante, // [char](1) NOT NULL, LETRA DEL COMPROBANTE (A,B,C,M,E) 4 TIP: afipTablas(comprobante.identificaxComprobante.tipo).letraComprobante, // [char](1) NOT NULL, LETRA DEL COMPROBANTE (A,B,C,M,E)
5 TCO: afipTablas(comprobante.identificaxComprobante.tipo).tipoComprobante, // [char](2) NOT NULL, TIPO DE COMPROBANTE (FT,NC,ND,RE,CI,LP) 5 TCO: afipTablas(comprobante.identificaxComprobante.tipo).tipoComprobante, // [char](2) NOT NULL, TIPO DE COMPROBANTE (FT,NC,ND,RE,CI,LP)
6 SUC: parseInt(comprobante.identificaxComprobante.puntoVenta), // [int] NOT NULL, PUNTO DE VENTA 6 SUC: parseInt(comprobante.identificaxComprobante.puntoVenta), // [int] NOT NULL, PUNTO DE VENTA
7 NCO: parseInt(comprobante.identificaxComprobante.numero), // [bigint] NOT NULL, NUMERO DE COMPROBANTE 7 NCO: parseInt(comprobante.identificaxComprobante.numero), // [bigint] NOT NULL, NUMERO DE COMPROBANTE
8 COD: entities.proveedores.COD, // [int] NOT NULL, CODIGO DEL PROVEEDOR NECESITAS RELACION -- BUSCAR SI ENVIAN EL CUIT DEL PROVEEDOR SELECT COD FROM PROVEED WHERE CUIT= '30-54775125-2' 8 COD: entities.proveedores.COD, // [int] NOT NULL, CODIGO DEL PROVEEDOR NECESITAS RELACION -- BUSCAR SI ENVIAN EL CUIT DEL PROVEEDOR SELECT COD FROM PROVEED WHERE CUIT= '30-54775125-2'
9 FEC: comprobante.identificaxComprobante.fechaComprobante, // [smalldatetime] NULL, FECHA DEL COMPROBANTE 9 FEC: comprobante.identificaxComprobante.fechaComprobante, // [smalldatetime] NULL, FECHA DEL COMPROBANTE
10 NOM: entities.proveedores.NOM, // [varchar](40) NOT NULL, NOMBRE DEL PROVEEDOR TABLA PROVEED CAMPO NOM 10 NOM: entities.proveedores.NOM, // [varchar](40) NOT NULL, NOMBRE DEL PROVEEDOR TABLA PROVEED CAMPO NOM
11 TIV: entities.proveedores.IVA, // [tinyint] NOT NULL, TIPO DE IVA CAMPO IVA TABLA PROVEED 11 TIV: entities.proveedores.IVA, // [tinyint] NOT NULL, TIPO DE IVA CAMPO IVA TABLA PROVEED
12 CUI: entities.proveedores.CUIT, // [char](13) NOT NULL, CUIT DEL PROVEEDOR CAMPO CUIT DEL PROVEEDOR O EL QUE VIENE EN LA COMUNICACION 12 CUI: entities.proveedores.CUIT, // [char](13) NOT NULL, CUIT DEL PROVEEDOR CAMPO CUIT DEL PROVEEDOR O EL QUE VIENE EN LA COMUNICACION
13 FPA: entities.proveedores.FPA, // [tinyint] NOT NULL, FORMA DE PAGO CAMPO FPA TABLA PROVEED 13 FPA: entities.proveedores.FPA, // [tinyint] NOT NULL, FORMA DE PAGO CAMPO FPA TABLA PROVEED
14 TCA: 1, // [money] NOT NULL, FIJO 1 14 TCA: 1, // [money] NOT NULL, FIJO 1
15 DTO: comprobante.descuentosGlobalesFactura.importe, // [money] NOT NULL, DESCUENTO TOTAL SUMATORIA DE LOS DTO POR ITEM 15 DTO: comprobante.descuentosGlobalesFactura.importe || 0, // [money] NOT NULL, DESCUENTO TOTAL SUMATORIA DE LOS DTO POR ITEM
16 PDT: 0, // [money] NOT NULL, FIJO 0 16 PDT: 0, // [money] NOT NULL, FIJO 0
17 NET: comprobante.importesTotales.netoGravado, // [money] NOT NULL, SUMATORIA DE LOS NETOS POR ITEM QUE TIENEN IVA <> 0 17 NET: comprobante.importesTotales.netoGravado, // [money] NOT NULL, SUMATORIA DE LOS NETOS POR ITEM QUE TIENEN IVA <> 0
18 NEE: comprobante.importesTotales.importeOperacionesExentas, // [money] NOT NULL, SUMATORIA DE LOS NETOS POR ITEM QUE TIENEN IVA = 0 18 NEE: comprobante.importesTotales.importeOperacionesExentas, // [money] NOT NULL, SUMATORIA DE LOS NETOS POR ITEM QUE TIENEN IVA = 0
19 IRI: comprobante.detallesImportesIVA.importeLiquidado, // [money] NOT NULL, SUMATORIA DE LOS IVA POR ITEM 19 IRI: comprobante.detallesImportesIVA.importeLiquidado, // [money] NOT NULL, SUMATORIA DE LOS IVA POR ITEM
20 IRS: 0, // [money] NOT NULL, FIJO 0 20 IRS: 0, // [money] NOT NULL, FIJO 0
21 IMI: comprobante.importesTotales.importeImpuestosInternos, // [money] NOT NULL, SUMATORIA DE LOS IMPUESTOS INTERNOS POR ITEM 21 IMI: comprobante.importesTotales.importeImpuestosInternos, // [money] NOT NULL, SUMATORIA DE LOS IMPUESTOS INTERNOS POR ITEM
22 RGA: 0, // [money] NOT NULL, IMPORTE RETENCION DE GANANCIAS 22 RGA: 0, // [money] NOT NULL, IMPORTE RETENCION DE GANANCIAS
23 RIB: 0, // [money] NOT NULL, IMPORTE RETENCION DE INGRESOS BRUTOS 23 RIB: 0, // [money] NOT NULL, IMPORTE RETENCION DE INGRESOS BRUTOS
24 PIV: null, // [money] NOT NULL, IMPORTE PERCEPCION DE IVA, SECTOR 90 C05 24 PIV: comprobante.detalleOtrosImpuestosComprobante.percepcionIVA ? comprobante.detalleOtrosImpuestosComprobante.percepcionIVA.importeImpuesto : 0, // [money] NOT NULL, IMPORTE PERCEPCION DE IVA, SECTOR 90 C05
25 CNG: comprobante.importesTotales.totalConceptosNoNetoGravado, // [money] NULL, IMPORTE DE CONCEPTOS NO GRAVADOS 25 CNG: comprobante.importesTotales.totalConceptosNoNetoGravado, // [money] NULL, IMPORTE DE CONCEPTOS NO GRAVADOS
26 TOT: comprobante.importesTotales.totalOperacion, // [money] NOT NULL, IMPORTE TOTAL DE LA FACTURA 26 TOT: comprobante.importesTotales.totalOperacion, // [money] NOT NULL, IMPORTE TOTAL DE LA FACTURA
27 ZON: entities.empresa.ZON, // [int] NOT NULL, NUMERO DE LA EMPRESA SELECT ZON FROM APAREMP 27 ZON: entities.empresa.ZON, // [int] NOT NULL, NUMERO DE LA EMPRESA SELECT ZON FROM APAREMP
28 FEV: comprobante.identificaxComprobante.fechaVencimiento, // [datetime] NULL, FECHA DE VENCIMIENTO 28 FEV: comprobante.identificaxComprobante.fechaVencimiento, // [datetime] NULL, FECHA DE VENCIMIENTO
29 OCP: comprobante.comprobantesReferencia[0].numeroDocumentoReferencia, // [char](10) NOT NULL, SI VIENE LA ORDEN DE COMPRA FORMATO "0000000000" (DOS PRIMERO PARA PVE Y 8 ULTIMOS EL NUMERO DE LA OC) 29 OCP: comprobante.comprobantesReferencia.PC.numeroDocumentoReferencia, // [char](10) NOT NULL, SI VIENE LA ORDEN DE COMPRA FORMATO "0000000000" (DOS PRIMERO PARA PVE Y 8 ULTIMOS EL NUMERO DE LA OC)
30 OPE: 0, // [int] NOT NULL, FIJO 0 30 OPE: 0, // [int] NOT NULL, FIJO 0
31 REC: 0, // [bigint] NOT NULL, FIJO 0 31 REC: 0, // [bigint] NOT NULL, FIJO 0
32 FEP: comprobante.identificaxComprobante.fechaComprobante, // [datetime] NULL, ITEM FECHA FACTURA 32 FEP: comprobante.identificaxComprobante.fechaComprobante, // [datetime] NULL, ITEM FECHA FACTURA
33 NPE: 0, // [bigint] NOT NULL, NOTA DE PEDIDO FIJO 0 33 NPE: 0, // [bigint] NOT NULL, NOTA DE PEDIDO FIJO 0
34 CPA: 0, // [int] NOT NULL, FIJO 0 34 CPA: 0, // [int] NOT NULL, FIJO 0
35 ENV: 0, // [int] NOT NULL, FIJO 0 35 ENV: 0, // [int] NOT NULL, FIJO 0
36 REM: 0, // [bigint] NOT NULL, FIJO 0 36 REM: 0, // [bigint] NOT NULL, FIJO 0
37 PRO: ' ', // [char](1) NOT NULL, FIJO ' ' VACIO NO NULO 37 PRO: ' ', // [char](1) NOT NULL, FIJO ' ' VACIO NO NULO
38 ANU: ' ', // [char](1) NOT NULL, FIJO ' ' VACIO NO NULO 38 ANU: ' ', // [char](1) NOT NULL, FIJO ' ' VACIO NO NULO
39 TUR: 0, // [int] NOT NULL, FIJO 0 39 TUR: 0, // [int] NOT NULL, FIJO 0
40 PLA: 0, // [int] NOT NULL, FIJO 0 40 PLA: 0, // [int] NOT NULL, FIJO 0
41 LUG: 0, // [int] NOT NULL, FIJO 0 41 LUG: 0, // [int] NOT NULL, FIJO 0
42 ATO: 0, // [numeric](18, 0) NOT NULL, FIJO 0 42 ATO: 0, // [numeric](18, 0) NOT NULL, FIJO 0
43 CCO: 0, // [bigint] NOT NULL, FIJO 0 43 CCO: 0, // [bigint] NOT NULL, FIJO 0
44 IMA: 0, // [int] NOT NULL, FIJO 0 44 IMA: 0, // [int] NOT NULL, FIJO 0
45 CCA1: 0, // [int] NOT NULL, FIJO 0 45 CCA1: 0, // [int] NOT NULL, FIJO 0
46 CCA2: 0, // [int] NOT NULL, FIJO 0 46 CCA2: 0, // [int] NOT NULL, FIJO 0
47 CCA3: 0, // [int] NOT NULL, FIJO 0 47 CCA3: 0, // [int] NOT NULL, FIJO 0
48 CCA4: 0, // [int] NOT NULL, FIJO 0 48 CCA4: 0, // [int] NOT NULL, FIJO 0
49 CCA5: 0, // [int] NOT NULL, FIJO 0 49 CCA5: 0, // [int] NOT NULL, FIJO 0
50 CCA6: 0, // [int] NOT NULL, FIJO 0 50 CCA6: 0, // [int] NOT NULL, FIJO 0
51 CCA7: 0, // [int] NOT NULL, FIJO 0 51 CCA7: 0, // [int] NOT NULL, FIJO 0
52 CCA8: 0, // [int] NOT NULL, FIJO 0 52 CCA8: 0, // [int] NOT NULL, FIJO 0
53 CCA0: 0, // [int] NOT NULL, FIJO 0 53 CCA0: 0, // [int] NOT NULL, FIJO 0
54 OBS: comprobante.importesTotales.observaciones, // [varchar](60) NOT NULL, SI VIENEN OBSERVACIONES PONER AQUI SINO VACIO NO NULO 54 OBS: comprobante.importesTotales.observaciones, // [varchar](60) NOT NULL, SI VIENEN OBSERVACIONES PONER AQUI SINO VACIO NO NULO
55 RIV: 0, // [money] NOT NULL, IMPORTE RETENCION DE IVA 55 RIV: 0, // [money] NOT NULL, IMPORTE RETENCION DE IVA
56 FECCAI: comprobante.identificaxComprobante.fechaVencimientoCai, // [smalldatetime] NOT NULL, FECHA DEL CAI 56 FECCAI: comprobante.identificaxComprobante.fechaVencimientoCai, // [smalldatetime] NOT NULL, FECHA DEL CAI
57 CAI: comprobante.identificaxComprobante.cai, // [char](16) NOT NULL, NUMERO DE CAI 57 CAI: comprobante.identificaxComprobante.cai, // [char](16) NOT NULL, NUMERO DE CAI
58 CHO: 0, // [int] NOT NULL, FIJO 0 58 CHO: 0, // [int] NOT NULL, FIJO 0
59 CTR: '', // [char](1) NOT NULL, VACIO NO NULO 59 CTR: '', // [char](1) NOT NULL, VACIO NO NULO
60 PER: comprobante.importesTotales.importeIB, // [money] NOT NULL, IMPORTE DE PERCEPCIONES 60 PER: comprobante.importesTotales.importeIB, // [money] NOT NULL, IMPORTE DE PERCEPCIONES
61 CCA9: 0, // [int] NOT NULL, FIJO 0 61 CCA9: 0, // [int] NOT NULL, FIJO 0
62 FECVEN: comprobante.identificaxComprobante.fechaVencimiento, // [smalldatetime] NOT NULL, FECHA DE VENCIMIENTO DE LA FACTURA 62 FECVEN: comprobante.identificaxComprobante.fechaVencimiento, // [smalldatetime] NOT NULL, FECHA DE VENCIMIENTO DE LA FACTURA
63 CNG2: 0, // [money] NOT NULL, IMPORTE DE CONCEPTOS NO GRAVADOS 2 63 CNG2: 0, // [money] NOT NULL, IMPORTE DE CONCEPTOS NO GRAVADOS 2
64 E_HD: '', // [varchar](8) NOT NULL, VACIO NO NULO 64 E_HD: '', // [varchar](8) NOT NULL, VACIO NO NULO
65 C_HD: '', // [varchar](1) NOT NULL, VACIO NO NULO 65 C_HD: '', // [varchar](1) NOT NULL, VACIO NO NULO
66 RSS: 0, // [money] NOT NULL, IMPORTE RETENCIONS SUSS 66 RSS: 0, // [money] NOT NULL, IMPORTE RETENCIONS SUSS
67 E_HD2: '', // [varchar](12) NOT NULL, VACIO NO NULO 67 E_HD2: '', // [varchar](12) NOT NULL, VACIO NO NULO
68 C_HD2: '', // [varchar](1) NOT NULL, VACIO NO NULO 68 C_HD2: '', // [varchar](1) NOT NULL, VACIO NO NULO
69 DTO2: 0, // [money] NOT NULL, IMPORTE DE OTROS DESCUENTOS 69 DTO2: 0, // [money] NOT NULL, IMPORTE DE OTROS DESCUENTOS
70 ENLP: 0, // [bit] NOT NULL, FIJO 0 70 ENLP: 0, // [bit] NOT NULL, FIJO 0
71 COD_TRANS: comprobante.identificaxComprobante.numeroRegistrado, // [bigint] NOT NULL, VER DE PONER EL NUMERO DE REFERENCIA QUE PUEDA UNIRNOS A LO QUE VIENE DESDE PLANEX 71 COD_TRANS: comprobante.identificaxComprobante.numeroRegistrado || 0, // [bigint] NOT NULL, VER DE PONER EL NUMERO DE REFERENCIA QUE PUEDA UNIRNOS A LO QUE VIENE DESDE PLANEX
72 RETMUN: comprobante.importesTotales.importeImpuestosMunicipales, // [money] NOT NULL, IMPORTE DE RETENCIONES MUNICIPALES 72 RETMUN: comprobante.importesTotales.importeImpuestosMunicipales, // [money] NOT NULL, IMPORTE DE RETENCIONES MUNICIPALES
73 TIPO_OPERACION: 0, // [int] NOT NULL, FIJO 0 73 TIPO_OPERACION: 0, // [int] NOT NULL, FIJO 0
74 IRD: 0, // [money] NOT NULL, FIJO 0 74 IRD: 0, // [money] NOT NULL, FIJO 0
75 AUX1: 0, // [money] NOT NULL, FIJO 0 75 AUX1: 0, // [money] NOT NULL, FIJO 0
76 AUX2: 0, // [money] NOT NULL, FIJO 0 76 AUX2: 0, // [money] NOT NULL, FIJO 0
77 AUX3: 0, // [money] NOT NULL, FIJO 0 77 AUX3: 0, // [money] NOT NULL, FIJO 0
78 AUX4: 0, // [money] NOT NULL, FIJO 0 78 AUX4: 0, // [money] NOT NULL, FIJO 0
79 ARBA: 0, // [money] NOT NULL, IMPORTE RETENCION ARBA 79 ARBA: 0, // [money] NOT NULL, IMPORTE RETENCION ARBA
80 DGR: 0, // [money] NOT NULL, IMPORTE RETENCION DGR 80 DGR: 0, // [money] NOT NULL, IMPORTE RETENCION DGR
81 DTO_PIE: 0, // [money] NOT NULL, IMPORTE DE DESCUENTO AL PIE, NO POR ITEM 81 DTO_PIE: 0, // [money] NOT NULL, IMPORTE DE DESCUENTO AL PIE, NO POR ITEM
82 OPERACIONES_3711: 1, // [int] NOT NULL, FIJO 1 (PORQUE SON BIENES) 82 OPERACIONES_3711: 1, // [int] NOT NULL, FIJO 1 (PORQUE SON BIENES)
83 ORC: 'TODO: comprobantesReferencia CUANDO ES PC', // [bigint] NOT NULL, NUMERO DE ORDEN DE COMPRA 83 ORC: comprobante.comprobantesReferencia.PC.numeroDocumentoReferencia, // [bigint] NOT NULL, NUMERO DE ORDEN DE COMPRA
84 NC_ES_NP: 0, // [bit] NOT NULL, FIJO 0 84 NC_ES_NP: 0, // [bit] NOT NULL, FIJO 0
85 CABA: 0, // [money] NOT NULL, IMPORTE RETENCION CABA 85 CABA: 0, // [money] NOT NULL, IMPORTE RETENCION CABA
86 ARBA_PER: 0, // [money] NOT NULL, IMPORTE PERCEPCION ARBA 86 ARBA_PER: 0, // [money] NOT NULL, IMPORTE PERCEPCION ARBA
87 CABA_PER: 0, // [money] NOT NULL, IMPORTE PERCEPCION CABA 87 CABA_PER: 0, // [money] NOT NULL, IMPORTE PERCEPCION CABA
88 PERMUN: comprobante.importesTotales.importeImpuestosMunicipales, // [money] NOT NULL, IMPORTE PERCEPCIONES MUNICIPALES 88 PERMUN: comprobante.importesTotales.importeImpuestosMunicipales, // [money] NOT NULL, IMPORTE PERCEPCIONES MUNICIPALES
89 IMI2: 0, // [money] NOT NULL, FIJO 0 89 IMI2: 0, // [money] NOT NULL, FIJO 0
90 }; 90 };
91 } 91 }
92 92
1 module.exports = function(comprobante, afipTablas, entities, item) { 1 module.exports = function(comprobante, afipTablas, entities, item) {
2 2
3 return { 3 return {
4 TIP: afipTablas(comprobante.identificaxComprobante.tipo).letraComprobante, // [char](1) NOT NULL, LETRA DEL COMPROBANTE (A,B,C,M) 4 TIP: afipTablas(comprobante.identificaxComprobante.tipo).letraComprobante, // [char](1) NOT NULL, LETRA DEL COMPROBANTE (A,B,C,M)
5 TCO: afipTablas(comprobante.identificaxComprobante.tipo).tipoComprobante, // [char](2) NOT NULL, TIPO DE COMPROBANTE (FT,NC,ND) 5 TCO: afipTablas(comprobante.identificaxComprobante.tipo).tipoComprobante, // [char](2) NOT NULL, TIPO DE COMPROBANTE (FT,NC,ND)
6 SUC: parseInt(comprobante.identificaxComprobante.puntoVenta), // [int] NOT NULL, PUNTO DE VENTA DE LA FACTURA 6 SUC: parseInt(comprobante.identificaxComprobante.puntoVenta), // [int] NOT NULL, PUNTO DE VENTA DE LA FACTURA
7 NCO: parseInt(comprobante.identificaxComprobante.numero), // [bigint] NOT NULL, NUMERO DE COMPROBANTE 7 NCO: parseInt(comprobante.identificaxComprobante.numero), // [bigint] NOT NULL, NUMERO DE COMPROBANTE
8 PRO: entities.proveedores.COD, // [int] NOT NULL, CODIGO DEL PROVEEDOR NECESITAS RELACION -- BUSCAR SI ENVIAN EL CUIT DEL PROVEEDOR SELECT COD FROM PROVEED WHERE CUIT= '30-54775125-2' 8 PRO: entities.proveedores.COD, // [int] NOT NULL, CODIGO DEL PROVEEDOR NECESITAS RELACION -- BUSCAR SI ENVIAN EL CUIT DEL PROVEEDOR SELECT COD FROM PROVEED WHERE CUIT= '30-54775125-2'
9 ORD: parseInt(item.numeroLinea), // [int] NOT NULL, ORDEN DEL ITEM, EMPIEZA EN 1 Y SUMA DE A 1 POR CADA REGISTRO DE MOVIMIENTO 9 ORD: parseInt(item.numeroLinea), // [int] NOT NULL, ORDEN DEL ITEM, EMPIEZA EN 1 Y SUMA DE A 1 POR CADA REGISTRO DE MOVIMIENTO
10 COD: item.CodSec, // [int] NOT NULL, SECTOR DEBO DEL PRODUCTO 10 COD: item.CodSec, // [int] NOT NULL, SECTOR DEBO DEL PRODUCTO
11 ART: item.CodArt, // [int] NOT NULL, ARTICULO DEBO DEL PRODUCTO ESTOS 2 SE OBTIENEN A PARTIR DEL CODIGO DE BARRAS: SELECT CodSec AS SECTOR,CodArt AS ARTICULO FROM CODBAR WHERE CODBAR='03239210540' 11 ART: item.CodArt, // [int] NOT NULL, ARTICULO DEBO DEL PRODUCTO ESTOS 2 SE OBTIENEN A PARTIR DEL CODIGO DE BARRAS: SELECT CodSec AS SECTOR,CodArt AS ARTICULO FROM CODBAR WHERE CODBAR='03239210540'
12 RUB: item.CodRub, // [int] NOT NULL, CODIGO DE RUBRO SE OBTIENE DE LA TABLA ARTICULOS SELECT DET_LAR,CODRUB FROM ARTICULOS WHERE CODSEC=SECTOR AND CODART=ARTICULO (DATOS OBTENIDOS EN NOTA ANTERIOR 12 RUB: item.CodRub, // [int] NOT NULL, CODIGO DE RUBRO SE OBTIENE DE LA TABLA ARTICULOS SELECT DET_LAR,CODRUB FROM ARTICULOS WHERE CODSEC=SECTOR AND CODART=ARTICULO (DATOS OBTENIDOS EN NOTA ANTERIOR
13 TIO: item.DET_LAR, // [varchar](60) NOT NULL DESCRIPCION DEL PRODUCTO DEL PUNTO ANTERIOR DET_LAR 13 TIO: item.DET_LAR, // [varchar](60) NOT NULL DESCRIPCION DEL PRODUCTO DEL PUNTO ANTERIOR DET_LAR
14 LI0: item.descripcion, // [varchar](60) NOT NULL, DESCRIPCION ENVIADA POR EL PROVEEDOR 14 LI0: item.descripcion, // [varchar](60) NOT NULL, DESCRIPCION ENVIADA POR EL PROVEEDOR
15 CAN: item.cantidad, // [money] NOT NULL, CANTIDAD DEL ITEM 15 CAN: item.cantidad, // [money] NOT NULL, CANTIDAD DEL ITEM
16 PUN: item.precioUnitario, // [decimal](20, 8) NOT NULL PRECIO UNITARIO DEL PRODUCTO ITEM 16 PUN: item.precioUnitario, // [decimal](20, 8) NOT NULL PRECIO UNITARIO DEL PRODUCTO ITEM
17 IMI: item.impuestoInterno ? item.impuestoInterno.importeImpuesto : 0, // [money] NOT NULL, IMPORTE IMPUESTOS INTERNOS DEL ITEM 17 IMI: item.impuestoInterno ? item.impuestoInterno.importeImpuesto : 0, // [money] NOT NULL, IMPORTE IMPUESTOS INTERNOS DEL ITEM
18 IVA: item.importeIVA, // [money] NOT NULL, IMPORTE IVA DEL ITEM 18 IVA: item.importeIVA, // [money] NOT NULL, IMPORTE IVA DEL ITEM
19 PUT: item.precioUnitario, // [money] NOT NULL, IGUAL AL PUN 19 PUT: item.precioUnitario, // [money] NOT NULL, IGUAL AL PUN
20 LEG: 0, // [int] NOT NULL, FIJO 0 20 LEG: 0, // [int] NOT NULL, FIJO 0
21 CMF: 0, // [int] NOT NULL, FIJO 0 21 CMF: 0, // [int] NOT NULL, FIJO 0
22 TUR: 0, // [int] NOT NULL, FIJO 0 22 TUR: 0, // [int] NOT NULL, FIJO 0
23 PLA: 0, // [int] NOT NULL, FIJO 0 23 PLA: 0, // [int] NOT NULL, FIJO 0
24 LUG: 0, // [int] NOT NULL, FIJO 0 24 LUG: 0, // [int] NOT NULL, FIJO 0
25 ESC: 0, // [bit] NOT NULL, FIJO 0 25 ESC: 0, // [bit] NOT NULL, FIJO 0
26 TAN: 0, // [int] NOT NULL, FIJO 0 26 TAN: 0, // [int] NOT NULL, FIJO 0
27 CCO: 0, // [bigint] NOT NULL, FIJO 0 27 CCO: 0, // [bigint] NOT NULL, FIJO 0
28 E_HD: '', // [varchar](8) NOT NULL, FIJO '' VACIO NO NULO 28 E_HD: '', // [varchar](8) NOT NULL, FIJO '' VACIO NO NULO
29 C_HD: '', // [varchar](1) NOT NULL, FIJO '' VACIO NO NULO 29 C_HD: '', // [varchar](1) NOT NULL, FIJO '' VACIO NO NULO
30 DTO: comprobante.detalleDescuentosItemFactura.importeDescuento, // [money] NOT NULL, IMPORTE DESCUENTO DE LA FACTURA 30 DTO: 0, // Comprobante.detalleDescuentosItemFactura.importeDescuento; [money] NOT NULL, IMPORTE DESCUENTO DE LA FACTURA
31 PTA: 0, // [int] NOT NULL, FIJO 0 31 PTA: 0, // [int] NOT NULL, FIJO 0
32 SUBM: 0, // [int] NOT NULL, FIJO 0 32 SUBM: 0, // [int] NOT NULL, FIJO 0
33 E_HD2: '', // [varchar](12) NOT NULL, FIJO '' VACIO NO NULO 33 E_HD2: '', // [varchar](12) NOT NULL, FIJO '' VACIO NO NULO
34 C_HD2: '', // [varchar](1) NOT NULL, FIJO '' VACIO NO NULO 34 C_HD2: '', // [varchar](1) NOT NULL, FIJO '' VACIO NO NULO
35 COMISION: 0, // [money] NOT NULL, FIJO 0 35 COMISION: 0, // [money] NOT NULL, FIJO 0
36 LIQ_VTA: '', // [varchar](20) NOT NULL, FIJO '' VACIO NO NULO 36 LIQ_VTA: '', // [varchar](20) NOT NULL, FIJO '' VACIO NO NULO
37 COSTO_PMOV: comprobante.itemsFactura.precioUnitario, // [money] NOT NULL, IGUAL AL PUN 37 COSTO_PMOV: comprobante.itemsFactura.precioUnitario, // [money] NOT NULL, IGUAL AL PUN
38 SAL_ITEM: 0, // [money] NOT NULL, fijo 0 es el que se llenara al mostrar en la tablet o telefono para que llene operador 38 SAL_ITEM: 0, // [money] NOT NULL, fijo 0 es el que se llenara al mostrar en la tablet o telefono para que llene operador
39 TASIVA: comprobante.itemsFactura.alicuotaIVAAplicable, // [money] NOT NULL, TASA DE IVA DEL ITEM = 21.00 / 10.50 / ETC. 39 TASIVA: comprobante.itemsFactura.alicuotaIVAAplicable, // [money] NOT NULL, TASA DE IVA DEL ITEM = 21.00 / 10.50 / ETC.
40 }; 40 };
41 } 41 }
42 42
1 config = require('./config/config.json'); 1 config = require('./config/config.json');
2 module.exports = knex = require('knex')(config.db)
2 3
3 require('./watch/index')(config.dir, onGetFile); 4 require('./watch/index')(config.dir, onGetFile);
4 5
5 const wsServer = require('./webSocketServer/index')(); 6 const wsServer = require('./webSocketServer/index')();
6 7
7 function onGetFile(event, fileString) { 8 function onGetFile(event, fileString) {
8 9
9 if (!fileString) return; 10 if (!fileString) return;
10 11
11 var planex = require('./planex/index')(fileString); 12 var planex = require('./planex/index')(fileString);
12 13
13 console.log(planex); 14 console.log(planex);
14 15
15 var entities = {}; 16 var entities = {};
16 17
17 var tipoCuit = planex.identificaxEmisor.cuit.slice(0, 2); 18 var tipoCuit = planex.identificaxEmisor.cuit.slice(0, 2);
18 var digitoVerificador = planex.identificaxEmisor.cuit[planex.identificaxEmisor.cuit.length - 1]; 19 var digitoVerificador = planex.identificaxEmisor.cuit[planex.identificaxEmisor.cuit.length - 1];
19 20
20 var cuitToDebo = tipoCuit + '-' + planex.identificaxEmisor.cuit.slice(2, 10) + '-' + digitoVerificador; 21 var cuitToDebo = tipoCuit + '-' + planex.identificaxEmisor.cuit.slice(2, 10) + '-' + digitoVerificador;
21 22
22 var promiseProveedores = wsServer.getEntidad('7790968003283', 'PROVEED', {CUIT: cuitToDebo}); 23 var promiseProveedores = wsServer.getEntidad('7790968003283', 'PROVEED', {CUIT: cuitToDebo});
23 var promiseEmp = wsServer.getEntidad('7790968003283', 'APAREMP'); 24 var promiseEmp = wsServer.getEntidad('7790968003283', 'APAREMP');
24 25
25 var promesasArticulo = []; 26 var promesasArticulo = [];
26 27
27 planex.itemsFactura.forEach(item => { 28 planex.itemsFactura.forEach(item => {
28 29
29 var queryString = 'select cb.*, art.CodRub, art.DET_LAR from CODBAR cb ' + 30 var queryString = 'select cb.*, art.CodRub, art.DET_LAR from CODBAR cb ' +
30 'join ARTICULOS art on cb.CodArt = art.CodArt and cb.CodSec = art.CodSec where cb.CodBar = \'' + 31 'join ARTICULOS art on cb.CodArt = art.CodArt and cb.CodSec = art.CodSec where cb.CodBar = \'' +
31 item.codigoUPCEAN13 + '\''; 32 item.codigoUPCEAN13 + '\'';
32 33
33 promesasArticulo.push(wsServer.getEntidad('7790968003283', null, {}, queryString)); 34 promesasArticulo.push(wsServer.getEntidad('7790968003283', null, {}, queryString));
34 }); 35 });
35 36
36 Promise.all(promesasArticulo).then(function(values) { 37 Promise.all(promesasArticulo).then(function(values) {
37 38
38 planex.itemsFactura.forEach((item, index) => { 39 planex.itemsFactura.forEach((item, index) => {
40
41 if (!values[index]) console.error('No se encontró el articulo');
42
39 item.CodArt = values[index].CodArt; 43 item.CodArt = values[index].CodArt;
40 item.CodSec = values[index].CodSec; 44 item.CodSec = values[index].CodSec;
41 item.CodRub = values[index].CodRub; 45 item.CodRub = values[index].CodRub;
42 item.DET_LAR = values[index].DET_LAR; 46 item.DET_LAR = values[index].DET_LAR;
43 }); 47 });
44 48
45 Promise.all([promiseProveedores, promiseEmp]).then(function(data) { 49 Promise.all([promiseProveedores, promiseEmp]).then(function(data) {
46 50
47 entities.proveedores = data[0]; 51 entities.proveedores = data[0];
48 entities.empresa = data[1]; 52 entities.empresa = data[1];
49 53
50 var debo = require('./debo/index')(planex, entities); 54 var debo = require('./debo/index')(planex, entities);
51 55
52 console.log(debo); 56 require('./db/index')(debo);
53 }); 57 });
54 }); 58 });
55 } 59 }
56 60
57 console.log('listen websocket port ' + config.port); 61 console.log('listen websocket port ' + config.port);
58 console.log('Ejecutar programa como administrador...'); 62 console.log('Ejecutar programa como administrador...');
59 63
1 { 1 {
2 "name": "websocketho", 2 "name": "websocketho",
3 "version": "0.0.1", 3 "version": "0.0.1",
4 "description": "WebSocket Head Office", 4 "description": "WebSocket Head Office",
5 "main": "index.js", 5 "main": "index.js",
6 "dependencies": { 6 "dependencies": {
7 "express": "^4.16.4", 7 "express": "^4.16.4",
8 "knex": "^0.16.5",
9 "mssql": "^5.1.0",
8 "ws": "^7.0.0" 10 "ws": "^7.0.0"
9 }, 11 },
10 "devDependencies": {}, 12 "devDependencies": {},
11 "scripts": { 13 "scripts": {
12 "test": "echo \"Error: no test specified\" && exit 1" 14 "test": "echo \"Error: no test specified\" && exit 1"
13 }, 15 },
14 "author": "Foca Software", 16 "author": "Foca Software",
15 "license": "ISC" 17 "license": "ISC"
16 } 18 }
17 19
planex/comprobantesReferencia.js
1 module.exports = function(comprobante) { 1 module.exports = function(comprobante, result) {
2 2
3 var comprobanteArr = comprobante.split(';'); 3 var comprobanteArr = comprobante.split(';');
4 4
5 return { 5 var comprobanteReferencia = {
6 tipoDocumentoReferencia: comprobanteArr[1], 6 tipoDocumentoReferencia: comprobanteArr[1],
7 puntoVentaReferencia: parseInt(comprobanteArr[2]), 7 puntoVentaReferencia: parseInt(comprobanteArr[2]),
8 numeroDocumentoReferencia: parseInt(comprobanteArr[3]), 8 numeroDocumentoReferencia: parseInt(comprobanteArr[3]),
9 fechaComprobanteReferencia: comprobanteArr[4], 9 fechaComprobanteReferencia: comprobanteArr[4],
10 cuitEmisorComprobanteAsociado: comprobanteArr[5] 10 cuitEmisorComprobanteAsociado: comprobanteArr[5]
11 } 11 }
12
13 result.comprobantesReferencia[comprobanteReferencia.tipoDocumentoReferencia] = comprobanteReferencia;
14
15 return;
12 } 16 }
13 17
planex/detalleImpuestosItemFactura.js
1 module.exports = function(comprobante, returnFloatByDecimals) { 1 module.exports = function(comprobante, returnFloatByDecimals, result) {
2 2
3 var comprobanteArr = comprobante.split(';'); 3 var comprobanteArr = comprobante.split(';');
4 4
5 return { 5 var detalleDescuentos = {
6 numeroLinea: comprobanteArr[1], 6 numeroLinea: comprobanteArr[1],
7 descripcionImpuesto: comprobanteArr[2], 7 descripcionImpuesto: comprobanteArr[2],
8 procentajeImpuesto: returnFloatByDecimals(comprobanteArr[3], 2), 8 procentajeImpuesto: returnFloatByDecimals(comprobanteArr[3], 2),
9 importeBase: returnFloatByDecimals(comprobanteArr[4], 2), 9 importeBase: returnFloatByDecimals(comprobanteArr[4], 2),
10 importeImpuesto: returnFloatByDecimals(comprobanteArr[5, 2]) 10 importeImpuesto: returnFloatByDecimals(comprobanteArr[5], 2)
11 }; 11 };
12
13 var item = result.itemsFactura.filter(function(item) {
14 return detalleDescuentos.numeroLinea == item.numeroLinea;
15 })[0];
16
17 switch (detalleDescuentos.descripcionImpuesto) {
18 case 'C05':
19 item.percepcionIVA = detalleDescuentos;
20 break;
21 case 'C06':
22 item.percepcionIIBB = detalleDescuentos;
23 break;
24 case 'C07':
25 item.impuestoInterno = detalleDescuentos;
26 break;
27 case 'C08':
28 item.impuestoAbasto = detalleDescuentos;
29 break;
30 case 'ITC':
31 item.impuestoTransferenciaCombustibles = detalleDescuentos;
32 break;
33 case 'C10':
34 item.percepcionImpuestosMunicipales = detalleDescuentos;
35 break;
36 default:
37 break;
38 }
39
40 return detalleDescuentos;
12 } 41 }
13 42
planex/detalleOtrosImpuestosComprobante.js
1 module.exports = function(comprobante, returnFloatByDecimals) { 1 module.exports = function(comprobante, returnFloatByDecimals, result) {
2 2
3 var comprobanteArr = comprobante.split(';'); 3 var comprobanteArr = comprobante.split(';');
4 4
5 return { 5 var detalleOtrosImpuestos = {
6 descripcionImpuesto: comprobanteArr[1], 6 descripcionImpuesto: comprobanteArr[1],
7 porcentaje: returnFloatByDecimals(comprobanteArr[2], 2), 7 porcentaje: returnFloatByDecimals(comprobanteArr[2], 2),
8 importeBase: returnFloatByDecimals(comprobanteArr[3], 2), 8 importeBase: returnFloatByDecimals(comprobanteArr[3], 2),
9 importeImpuesto: returnFloatByDecimals(comprobanteArr[4], 2), 9 importeImpuesto: returnFloatByDecimals(comprobanteArr[4], 2),
10 codigoArancelImpuestoOCuota: comprobanteArr[5], 10 codigoArancelImpuestoOCuota: comprobanteArr[5],
11 jurisdiccion: comprobanteArr[6] 11 jurisdiccion: comprobanteArr[6]
12 }; 12 };
13
14 switch (detalleOtrosImpuestos.codigoArancelImpuestoOCuota) {
15 case 'C05':
16
17 result.detalleOtrosImpuestosComprobante.percepcionIVA = detalleOtrosImpuestos;
18 break;
19
20 case 'C07':
21
22 result.detalleOtrosImpuestosComprobante.impuestoInterno = detalleOtrosImpuestos;
23 break;
24
25 case 'C08':
26
27 result.detalleOtrosImpuestosComprobante.impuestoAbasto = detalleOtrosImpuestos;
28 break;
29
30 case 'C09':
31
32 result.detalleOtrosImpuestosComprobante.impuestoVideo = detalleOtrosImpuestos;
33 break;
34
35 case 'ITC':
36
37 result.detalleOtrosImpuestosComprobante.impuestoTransferenciaCombustibles = detalleOtrosImpuestos;
38 break;
39
40 case 'C12':
41
42 result.detalleOtrosImpuestosComprobante.percepcionNoCategorizadosORNI = detalleOtrosImpuestos;
43 break;
44 default:
45 break;
46 }
47
48 return;
13 } 49 }
14 50
1 module.exports = function(comprobante) { 1 module.exports = function(comprobante) {
2 2
3 // split por salto de línea 3 // split por salto de línea
4 comprobante = comprobante.split(/\r?\n/); 4 comprobante = comprobante.split(/\r?\n/);
5 5
6 var objReturn = { 6 var objReturn = {
7 identificaxComprobante: {}, 7 identificaxComprobante: {},
8 identificaxMensaje: {}, 8 identificaxMensaje: {},
9 comprobantesReferencia: [], 9 comprobantesReferencia: {},
10 identificaxEmisor: {}, 10 identificaxEmisor: {},
11 informaxRepresentanteEmisor: {}, 11 informaxRepresentanteEmisor: {},
12 identificaxReceptorFactura: {}, 12 identificaxReceptorFactura: {},
13 identificaxSucursalReceptorFactura: {}, 13 identificaxSucursalReceptorFactura: {},
14 importesTotales: {}, 14 importesTotales: {},
15 detallesImportesIVA: {}, 15 detallesImportesIVA: {},
16 detallePercepcionesIIBB: {}, 16 detallePercepcionesIIBB: {},
17 descuentosGlobalesFactura: {}, 17 descuentosGlobalesFactura: {},
18 detalleOtrosImpuestosComprobante: {}, 18 detalleOtrosImpuestosComprobante: {},
19 itemsFactura: [], 19 itemsFactura: [],
20 detalleDescuentosItemFactura: [], 20 detalleDescuentosItemFactura: [],
21 detalleImpuestosItemFactura: [] 21 detalleImpuestosItemFactura: []
22 }; 22 };
23 23
24 function returnFloatByDecimals(parameter, cantDecimal) { 24 function returnFloatByDecimals(parameter, cantDecimal) {
25 25
26 if (!parameter) return; 26 if (!parameter) return;
27 27
28 var beforeSemiColon = parseFloat(parameter.slice(0, parameter.length - cantDecimal)); 28 var beforeSemiColon = parseFloat(parameter.slice(0, parameter.length - cantDecimal));
29 29
30 var afterSemicolon = parameter.slice(parameter.length - cantDecimal, parameter.length); 30 var afterSemicolon = parameter.slice(parameter.length - cantDecimal, parameter.length);
31 31
32 return parseFloat(beforeSemiColon + '.' + afterSemicolon); 32 return parseFloat(beforeSemiColon + '.' + afterSemicolon);
33 } 33 }
34 34
35 comprobante.forEach(sector => { 35 comprobante.forEach(sector => {
36 36
37 if (sector.slice(0, 3) == '010') { 37 if (sector.slice(0, 3) == '010') {
38 objReturn.identificaxComprobante = require('./identificaxComprobante')(sector)// 010 38 objReturn.identificaxComprobante = require('./identificaxComprobante')(sector)// 010
39 } else if (sector.slice(0, 3) == '012') { 39 } else if (sector.slice(0, 3) == '012') {
40 objReturn.identificaxMensaje = require('./identificaxMensaje')(sector)// 012 40 objReturn.identificaxMensaje = require('./identificaxMensaje')(sector)// 012
41 } else if (sector.slice(0, 3) == '020') { 41 } else if (sector.slice(0, 3) == '020') {
42 objReturn.comprobantesReferencia.push(require('./comprobantesReferencia')(sector)) // 020 42 require('./comprobantesReferencia')(sector, objReturn) // 020
43 } else if (sector.slice(0, 3) == '030') { 43 } else if (sector.slice(0, 3) == '030') {
44 objReturn.identificaxEmisor = require('./identificaxEmisor')(sector) // 030 44 objReturn.identificaxEmisor = require('./identificaxEmisor')(sector) // 030
45 } else if (sector.slice(0, 3) == '035') { 45 } else if (sector.slice(0, 3) == '035') {
46 objReturn.informaxRepresentanteEmisor = require('./informaxRepresentanteEmisor')(sector) // 035 46 objReturn.informaxRepresentanteEmisor = require('./informaxRepresentanteEmisor')(sector) // 035
47 } else if (sector.slice(0, 3) == '040') { 47 } else if (sector.slice(0, 3) == '040') {
48 objReturn.identificaxReceptorFactura = require('./identificaxReceptorFactura')(sector) // 040 48 objReturn.identificaxReceptorFactura = require('./identificaxReceptorFactura')(sector) // 040
49 } else if (sector.slice(0, 3) == '045') { 49 } else if (sector.slice(0, 3) == '045') {
50 objReturn.identificaxSucursalReceptorFactura = require('./identificaxSucursalReceptorFactura')(sector) // 045 50 objReturn.identificaxSucursalReceptorFactura = require('./identificaxSucursalReceptorFactura')(sector) // 045
51 } else if (sector.slice(0, 3) == '050') { 51 } else if (sector.slice(0, 3) == '050') {
52 objReturn.importesTotales = require('./importesTotales')(sector, returnFloatByDecimals) // 050 52 objReturn.importesTotales = require('./importesTotales')(sector, returnFloatByDecimals) // 050
53 } else if (sector.slice(0, 3) == '060') { 53 } else if (sector.slice(0, 3) == '060') {
54 objReturn.detallesImportesIVA = require('./detallesImportesIVA')(sector, returnFloatByDecimals) // 060 54 objReturn.detallesImportesIVA = require('./detallesImportesIVA')(sector, returnFloatByDecimals) // 060
55 } else if (sector.slice(0, 3) == '070') { 55 } else if (sector.slice(0, 3) == '070') {
56 objReturn.detallePercepcionesIIBB = require('./detallePercepcionesIIBB')(sector, returnFloatByDecimals) // 070 56 objReturn.detallePercepcionesIIBB = require('./detallePercepcionesIIBB')(sector, returnFloatByDecimals) // 070
57 } else if (sector.slice(0, 3) == '080') { 57 } else if (sector.slice(0, 3) == '080') {
58 objReturn.descuentosGlobalesFactura = require('./descuentosGlobalesFactura')(sector, returnFloatByDecimals) // 080 58 objReturn.descuentosGlobalesFactura = require('./descuentosGlobalesFactura')(sector, returnFloatByDecimals) // 080
59 } else if (sector.slice(0, 3) == '090') { 59 } else if (sector.slice(0, 3) == '090') {
60 objReturn.detalleOtrosImpuestosComprobante = require('./detalleOtrosImpuestosComprobante')(sector, returnFloatByDecimals) // 090 60 require('./detalleOtrosImpuestosComprobante')(sector, returnFloatByDecimals, objReturn) // 090
61 } else if (sector.slice(0, 3) == '100') { 61 } else if (sector.slice(0, 3) == '100') {
62 objReturn.itemsFactura.push(require('./itemsFactura')(sector, returnFloatByDecimals)); // 100 62 objReturn.itemsFactura.push(require('./itemsFactura')(sector, returnFloatByDecimals)); // 100
63 } else if (sector.slice(0, 3) == '110') { 63 } else if (sector.slice(0, 3) == '110') {
64 objReturn.detalleDescuentosItemFactura = require('./detalleDescuentosItemFactura')(sector, returnFloatByDecimals); // 110 64 objReturn.detalleDescuentosItemFactura.push(require('./detalleDescuentosItemFactura')(sector, returnFloatByDecimals)); // 110
65 } else if (sector.slice(0, 3) == '120') { 65 } else if (sector.slice(0, 3) == '120') {
66 objReturn.detalleImpuestosItemFactura.push(require('./detalleImpuestosItemFactura')(sector, returnFloatByDecimals)); // 120 66 objReturn.detalleImpuestosItemFactura.push(require('./detalleImpuestosItemFactura')(sector, returnFloatByDecimals, objReturn)); // 120
67 }
68 });
69
70 if (!objReturn.detalleImpuestosItemFactura.length) {
71 return objReturn;
72 }
73
74 objReturn.itemsFactura.forEach(item => {
75
76 var detalleDescuentos = objReturn.detalleImpuestosItemFactura.filter(function(descuento) {
77 return descuento.numeroLinea == item.numeroLinea;
78 })[0];
79
80 switch (detalleDescuentos.descripcionImpuesto) {
81 case 'c05':
82 item.percepcionIVA = detalleDescuentos;
83 break;
84 case 'c06':
85 item.percepcionIIBB = detalleDescuentos;
86 break;
87 case 'c07':
88 item.impuestoInterno = detalleDescuentos;
89 break;
90 case 'c08':
91 item.impuestoAbasto = detalleDescuentos;
92 break;
93 case 'ITC':
94 item.impuestoTransferenciaCombustibles = detalleDescuentos;
95 break;
96 case 'c10':
97 item.percepcionImpuestosMunicipales = detalleDescuentos;
98 break;
99 default:
100 break;
101 } 67 }
102 }); 68 });
103 69
104 return objReturn; 70 return objReturn;
105 } 71 }
106 72
1 module.exports = function(dir, callback) { 1 module.exports = function(dir, callback) {
2 2
3 const fs = require('fs'); 3 const fs = require('fs');
4 4
5 fs.watch(dir, function(event, file) { 5 fs.watch(dir, function(event, file) {
6 6
7 var extencion = file.split('.')[1]; 7 var extencion = file.split('.')[1];
8 8
9 if (extencion == 'plx' && event == 'change') { 9 if (extencion == 'txt' && event == 'change') {
10 10
11 fs.readFile(dir + '\\' + file, 'utf8', function(err , fileString) { 11 fs.readFile(dir + '\\' + file, 'utf8', function(err , fileString) {
12 12
13 callback(event, fileString); 13 callback(event, fileString);
14 }) 14 });
15 } 15 }
16 16
17 }); 17 });
18 18
19 }; 19 };
20 20