OSDN Git Service

[REM] inout
[iphwproject/opentck3.git] / parser.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 __licence__ = "GNU/GPLv3"
4 __author__ = "Marcelo Zunino (InfoPrimo SL) 2015-2017"
5
6 import ipdb
7 # ipdb.set_trace()
8
9 import logging
10 import inspect as insp
11 from decimal import Decimal
12 from util import config
13 from spazospy.ticket import IPLinea
14 from openxmlrpc import OpenConn
15 import os.path as path
16
17 settings = config.dbSettings
18 op_conn = OpenConn(settings)
19 ns = __name__
20
21
22 class Excepcion(object):
23
24     stdout_err  = 1  # `stdout_err = 1` mostrará errores en stdout
25     verbose     = 1  # `verbose = 1`    mostrará detalles del error
26     debug_log   = 0  # `debug = 1`      escribe detalles en el log
27     debug_vivo  = 1  # `debug_vivo = 1` abre consola de debug en el error
28
29     def __init__(self, mensaje, frame=None, id_ticket=None):
30         # type: (object, object, object) -> object
31         self.msg = mensaje or " algo salió mal... "
32         self.msgv = ''
33         self.frame = frame
34         self.id_ticket = id_ticket
35
36     def excep(self):
37         """ logging / notificación a stdout """
38         msg = self.msg
39         msgv = self.msgv
40         frame = self.frame
41         id_ticket = self.id_ticket
42         if self.stdout_err and msg:
43             print("\t %s" % (msg,))
44         if self.verbose and frame and id_ticket:
45             msgv = "aaaammdd cja tck: %s" % (id_ticket,)
46             msgv += " en: %s  lín: %s" % (frame.filename, frame.lineno)
47             print("\t %s" % (msgv,))
48         if self.debug_log:
49             msg += msgv
50         msg += " fin ejecución..."
51         if self.debug_vivo:
52             import ipdb
53             ipdb.set_trace()
54         return True
55         # return sys.exit(1)
56
57
58 excepcion = Excepcion  # type: Type[Excepcion]
59
60
61 def erp_product_id(cod):
62     result = {}
63     try:
64         prod_id = op_conn.sock_execute('product.template', 'search', [('cod_sto', '=', cod)])
65         if prod_id and len(prod_id):
66             result[cod] = prod_id[0]
67         else:
68             ean_id = op_conn.sock_execute('product.ean13', 'search', [('name', '=', cod)])
69             if ean_id:
70                 product = op_conn.sock_execute('product.ean13', 'read', [ean_id])
71                 if product and len(product):
72                     prod_id = product[0]['product_id'][0]
73                     if prod_id:
74                         result[cod] = prod_id
75     except:
76         # import ipdb
77         # ipdb.set_trace()
78         return False
79     return result
80
81
82 def parse_lines(cabezal_ticket, lineas_ticket):
83     """
84      # parse_lines(C.pos_ticket, lineas_tck_pazos)
85     :param cabezal_ticket:          diccionario con datos del cabezal
86     :param lineas_ticket:        lineas del ticket
87
88     :return:     diccionario { cabezal: [linea, linea, linea...] }
89     """
90
91     """
92         Recibe un cabezal de ticket y una lista de líneas de ticket.
93         Instanciará un objeto de la clase `IPLinea`
94         Devuelve un diccionario (cabezal y líneas) del modelo en openerp.
95
96
97         Una particularidad de las líneas de Salidapazos es practicamente en la totalidad
98         de los tickets es que estas contienen datos típicos de cabezal que deben ser
99         extraídos y transformados en líneas de tipo cabezal. (medio de pago, cliente,
100         Id de la cajera, etc.)
101
102         Un ticket puede dar lugar a varios objetos de tipo cabezal diferentes.
103
104         Por ejemplo, en un ticket el nombre del cliente no es un dato frecuente.
105         No obstante si Salidapazos debe consignar un cliente específico, creará una
106         *línea* de detalle de ticket. Estos datos afectan a todas las líneas
107         del ticket. Por tal motivo, a nivel del ERP el objeto que los represente deberá
108         soportar una relación con una entidad o agente específico. Esta relación se
109         debe establlecer a partir del cabezal del ticket en el ERP.
110
111         Similar tratamiento llevan todos los tickets de venta o ingresos en lo que
112         refiere a los datos del medio o los medios de pago afectados a estos tickets.
113         Es decir, el detalle del medio de pago siempre es una *línea* del ticket en
114         Salidpazos. En cambio será un elemento del cabezal en el ERP.
115
116         Las razones de este tipo de estructura en Salidapazos... bueno se supone que
117         la expansión de funcionalidades que los POS son capaces de realizar ha
118         comprometido consecuentemente los diseños y estructuras subyasentes, constreñídas
119         por la necesidad de asegurar compatibilidad con stock muy diverso de aplicaciones
120         consumidoras de estos datos.
121
122         En la actualidad son tantas las variantes que puede tener un ticket que sus
123         cabezales deberían ser enormes para representar todos los tipos de tickets
124         posibles. Hay que admitirlo, la formalización de estas estructuras de datos
125         presenta desafíos muy interesantes.
126
127         La dificultad mayor radica en el parseo de las lineas de detalle del ticket,
128         dada la cantidad de tipos de líneas que contienen datos necesarios para el cabezal
129         de facturación. Ejemplo: detalles del medio de pago.
130
131
132         nota de diseño, 29/11/17:
133             Además de deserializar los CSV de Salidapazos, extraer los datos significativos,
134             esta rutina clasifica, tranforma o combina las líneas que contengan datos de
135             cabezal, creando incluso nuevas líneas de cabezal de ticket.
136
137             Considerando todos los tipos de líneas posibles, las líneas que contienen
138             datos de *cabezal* abarcan un amplio conjunto de tipos de líneas de detalle de
139             ticket diferetes.
140             En tando para las líneas que contienen datos típicos de *línea*, alcanza con tres
141             o cuatro tipos diferentes de líneas de detalle de ticket. Por este motivo el
142             parseo de líneas se vuelve más y más complejo a medida que se incorporan nuevas
143             necesidades para atender análisis de datos.
144
145             Una posibilidad de reducir la complejidad, sería quitar las tareas de modificación,
146             mergeo y creación de líneas de cabezal, dejando que las líneas sean simplemente
147             parseadas, sin modificar la estructura del ticket.
148
149             El resto de las tareas quedarían en otro método específico.
150
151             Finalmente serían creados los obetos python a ser serializados o entregado en una api.  
152     
153     """
154     # import ipdb
155     # ipdb.set_trace()
156     res = list()
157     tkfe = "%s %s %s" % (cabezal_ticket['numerotck'], cabezal_ticket['codigocaja'], cabezal_ticket['date'])
158
159     llave_47 = dict()   # cobranza
160     llave_68 = ''       # cobranza
161     llave_118 = None    #
162     llave_123 = dict()  #
163     llave_126 = dict()  #
164     llave_127 = dict()  #
165     tacre123_id = None  #
166
167     mediosdepago = {
168         'cuentas_tck': list(),
169         'tarjetas_tck': list(),
170         'cheques_tck': list(),
171         'devenvases_tck': list(),
172         'efectivo_tck': list(),
173         'puntos_tck': list(),
174         'tacrt_tck': list(),
175         'mides_tck': list(),
176         }
177     comprobantes = {
178         'egresocaja_tck': list(),
179         'retiros_tck': list(),
180         'almuerzo_tck': list(),
181         }
182     redondeos_tck = list()
183     cobranzas_tck = dict()            ###### SOLO ARREGLE ESTA
184
185     cabezal_ticket['cfe'] = dict()
186     cabezal_ticket['vouchertar_tck'] = list()
187     # if ttimestamp == '20171201194203':  # es cabezal[4] o C.timestamp
188     # if cabezal_ticket['numerotck'] == 84174 and cabezal_ticket.caja == 1:
189
190     parar = ''
191     for linea in lineas_ticket:
192         lin = IPLinea(linea, cabezal_ticket['name'])  # ticket_id
193         llave = lin.llave
194         data = lin.metodo()
195         # print llave, lin.descripcion
196
197         # Datos comunes en todos los tipos de líneas (de venta)
198         tck_line = dict(
199             tck_id = cabezal_ticket['name'],
200             name = lin.id_linea,
201             numerodelinea = lin.numerodelinea,
202             tipolinea = llave,
203             descripcion_lin = lin.descripcion,
204             hora = lin.hora,
205             codigoarticulo = 'codigo art.',
206             nota = '',
207             )
208
209         if llave == '1':
210             # 'Venta de ítem'
211             # Los calculos extraen los montos finales de venta
212             importe_iva = Decimal(data['ivadescuentototal'])
213             importe_siva = Decimal(data['preciodescuentototal'])
214             importe_civa = importe_siva + importe_iva
215             cantidad = Decimal(data['cantidad'])
216             punit_siniva = importe_siva / cantidad
217             punit_coniva = importe_civa / cantidad
218
219             tck_line.update(dict(
220                 codigoiva = data['codigoiva'],
221                 cantidad = round(cantidad, 2),
222                 lineacancelada = int(data['lineacancelada']),
223                 modoingreso = data['modoingreso'],
224                 codigoarticulo = data['codigoarticulo'],
225                 codigooriginal = data['codigoarticulooriginal'],
226                 estandem = int(data['siestandem']),
227                 preciounitario = round(Decimal(data['preciounitario']), 2),
228                 # precio unitario "de lista" con iva sin descuentos.
229                 cantdescmanuales = data['cantdescmanuales'],
230                 importe_siva = round(importe_siva, 2),
231                 importe_civa = round(importe_civa, 2),
232                 importe_iva = round(importe_iva, 2),
233                 punit_siniva = round(punit_siniva, 2),
234                 punit_coniva = round(punit_coniva, 2)
235             ))
236             if data['codigoarticulo'].isdigit():
237                 product_id = erp_product_id(data['codigoarticulo'])
238                 if product_id:
239                     tck_line['product_id'] = product_id
240             else:
241                 if not data['codigoarticulooriginal']:
242                     verbose = 1
243                     msg = "[ERROR]: No hay codigoarticulo ni codigooriginal: %s %s %s" % (
244                                                     llave,
245                                                     lin.descripcion,
246                                                     "%s %s %s" % (cabezal_ticket['numerotck'],
247                                                                   cabezal_ticket['codigocaja'],
248                                                                   cabezal_ticket['date'])
249                         )
250                     frame = insp.getframeinfo(insp.currentframe()) if verbose else False
251                     excepcion(msg, frame, cabezal_ticket)
252                     raise excepcion(msg, frame, cabezal_ticket)
253
254             # ivadescuentototal    =
255             # preciodescuentototal = ,
256             # codigovendedor    = data['codigovendedor'],
257             # talle             = data['talle'],
258             # color             = data['color'],
259             # marca             = data['marca'],
260             # modelo            = data['modelo'],
261             # siaplicadescfidel = data['siaplicadescfidel'],            # fidellización
262             # montorealdescfidel= float(data['montorealdescfidel']
263
264         elif llave == '4':
265             # 'Total del ticket (discrimina pago de servicios)'
266             cabezal_ticket['totalticket'] = round(Decimal(data['totalticket']), 2)
267             cabezal_ticket['totalticketsinpagoservicios'] = round(Decimal(data['totalticketsinpagoservicios']), 2)
268             cabezal_ticket['ivatotalticket'] = round(Decimal(data['ivatotalticket']), 2)
269             cabezal_ticket['ivatotalticketsinpagoservicios'] = round(
270                 Decimal(data['ivatotalticketsinpagoservicios']), 2)
271
272         elif llave == '5':
273             # Línea de cabezal CFE (5)  cfe_tck = {'cab': None, 'pie': None}
274             cabezal_ticket['cfe'].update(dict(
275                 tipocfe = data['tipocfe'],
276                 descripcioncfe = data['descripcioncfe'],
277                 seriecfe = data['seriecfe'],
278                 numerocfe = data['numerocfe'],
279                 tipodocumentoreceptor = data['tipodocumentoreceptor'],
280                 documentoreceptor = data['documentoreceptor'],
281                 nombrereceptor = data['nombrereceptor'],
282                 direccionreceptor = data['direccionreceptor'],
283                 ciudadreceptor = data['ciudadreceptor']))
284
285         elif llave == '6':
286             # Pie de CFE
287             cabezal_ticket['cfe'].update(dict(
288                 cliente = data['cliente'],
289                 linkdgi = data['linkdgi'],
290                 tipocfe = data['tipocfe'],
291                 rucemisor = data['rucemisor'],
292                 numerocfe = data['numerocfe'],
293                 fechacfe = data['fechacfe'],
294                 montoneto = data['montoneto'],
295                 hash_cfe = data['hash'],
296                 codigocae = data['codigocae'],
297                 seriecfe = data['seriecfe'],
298                 nroiniciocae = data['nroiniciocae'],
299                 nrofincae = data['nrofincae'],
300                 fechavencimientocae = data['fechavencimientocae']))
301
302         elif llave == '7':
303             # 'Identificación de la cajera'
304             # No tiene importancia conservarlo cómo línea de ticket
305             # alcanza con cargar el dato `nombrecajera` en el cabezal
306             # En tanto el `codigocajera` que viene el el cabezal,
307             # está duplicado en la línea. De haber inconsistencia
308             # se toma el de la línea
309
310             cabezal_ticket['nombrecajera'] = data['nombrecajera']
311             if cabezal_ticket['codigocajera'] != data['codigocajera']:
312                 cabezal_ticket['codigocajera'] = data['codigocajera']
313
314         elif llave == '9':
315             # 'Pago de ticket en efectivo
316             # import ipdb;ipdb.set_trace()
317
318             llave_9 = dict(
319                 tipo_medio = 'Efectivo',
320                 codigomediopago = data['codigomediopago'],
321                 codigomoneda = data['codigomoneda'],
322                 totalmediopagomoneda = round(Decimal(data['totalmediopagomoneda']), 2),
323                 totalmediopagomonedamonedareferencia = round(Decimal(data['totalmediopagomonedamonedareferencia']),
324                                                              2),
325                 totalpagado = round(Decimal(data['totalpagado']), 2),
326                 totalpagadomonedareferencia = round(Decimal(data['totalpagadomonedareferencia']), 2),
327                 cambio = round(Decimal(data['cambio']), 2),
328                 tipooperacion = data['tipooperacion'],
329                 lineaultimopago = data['lineaultimopago'],
330                 autorizasupervisora = data['autorizasupervisora'],
331                 codigosupervisora = data['codigosupervisora'],
332                 lineacancelada = data['lineacancelada']
333             )
334
335             mediosdepago['efectivo_tck'].append(llave_9)
336
337         elif llave == '10': NO esto es linea de CABEZAL de ticket
338             pass  # 10 Pago contra comprobante  Supervisor
339
340         elif llave == '12':
341
342             try:
343
344                 # 'Cancelación de Ítem'
345                 codigo = cancela_tipo = ''
346                 if data['indicadorartsubf'] == 'C':
347                     nota = (data['importe_cancelado'], data['nombresupervisora'])
348                     tck_line.update(dict(cancela_tipo = "Cancela Cobranza",
349                                          nota = nota, ))
350                 else:
351                     if data['indicadorartsubf'] == 'A':
352                         cancela_tipo = 'Cancela articulo'
353                         codigo = data['codigoarticulosubf'] if 'codigoarticulosubf' in data else 'sin articulo'
354
355                     elif data['indicadorartsubf'] == 'S':
356                         cancela_tipo = 'Cancela a subfamilia'
357                         codigo = data['codigoarticulosubf']
358
359                     elif data['indicadorartsubf'] == 'T':
360                         cancela_tipo = 'Art. cancelado es un tandem'
361                         codigo = data['codigoarticulo'] if 'codigoarticulo' in data else data['codigoarticulosubf']
362
363                     importe_civa = Decimal(data['importe_cancelado'])
364
365                     tck_line.update(dict(
366                         codigoarticulo = codigo,
367                         cancela_tipo = cancela_tipo,
368                         cantidad = 1.0,
369                         nrolineavta = data['nrolineavta'],
370                         importe_civa = round(importe_civa, 2),
371                         nota = data['nombresupervisora'],
372                     ))  # codigovendedor = data['codigovendedor'],
373
374                     if codigo.isdigit():
375                         product_id = erp_product_id(codigo)
376                         if product_id:
377                             tck_line['product_id'] = product_id
378             except Excepcion as ex:
379                 print ex
380                 import ipdb
381                 ipdb.set_trace()
382
383         elif llave == '18':   NO es linea de CABEZAL de ticket
384             pass  # 18 Retiros Supervisor
385
386         elif llave == '20':
387             # 'Devolución de un ítem'
388
389             """
390                 No discriminamos procesamos descuentos en las devoluciones
391                 preciodescuentototal    = data['preciodescuentototal']
392                 ivadescuentototal       = data['ivadescuentototal']
393                 preciodescuento         = data['preciodescuento']
394
395                             codigoarticulosubf      = lin[ 0] or None,
396                             cantidad                = lin[ 1] or None,
397                             precio                  = lin[ 2] or None,
398                             iva                     = lin[ 3] or None,
399                             indicadorartsubf        = lin[ 4] or None,
400                             codigosupervisora       = lin[ 5] or None,
401                             codigoarticulooriginal  = lin[ 6] or None,
402                             modoingreso             = lin[ 7] or None,
403                             codigovendedor          = lin[ 8] or ' ',
404                             lineacancelada          = lin[ 9] or None,
405                             preciodescuento         = lin[10] or None,
406                             ivadescuento            = lin[11] or None,
407                             codigoiva               = lin[12] or None,
408             """
409             if data['lineacancelada']:
410                 continue
411
412             if data['indicadorartsubf'] == 'S':
413                 tck_line['nota'] = ' Devol. a subfamilia'
414                 tck_line['codigoarticulo'] = data['codigoarticulosubf']
415
416             elif data['indicadorartsubf'] == 'A':
417                 tck_line['nota'] = ' Devol. de artículo'
418                 tck_line['codigoarticulo'] = data['codigoarticulosubf']
419
420             cantidad = Decimal(data['cantidad'])
421             importe_iva = Decimal(data['ivadescuento'])
422             importe_siva = Decimal(data['preciodescuento'])  # hay una inconsistencia en salidapazos * cantidad ??
423             importe_civa = importe_siva + importe_iva
424             punit_siniva = importe_siva / cantidad
425             punit_coniva = importe_civa / cantidad
426
427             tck_line.update(dict(
428                 cantidad = round(cantidad, 3),
429                 importe_iva = round(importe_iva, 2),
430                 importe_siva = round(importe_siva, 2),
431                 importe_civa = round(importe_civa, 2),
432                 punit_siniva = round(punit_siniva, 2),
433                 punit_coniva = round(punit_coniva, 2),
434
435                 supervisora = data['codigosupervisora'],
436                 codigooriginal = data['codigoarticulooriginal'],
437                 modoingreso = data['modoingreso'],
438                 nota = "Cod. Supervisor/a: " + data['codigosupervisora'],
439
440                 codigovendedor = data['codigovendedor'],
441                 lineacancelada = data['lineacancelada'],
442                 codigoiva = data['codigoiva'],
443             ))
444             if data['codigoarticulo'].isdigit():
445                 product_id = erp_product_id(data['codigoarticulo'])
446                 if product_id:
447                     tck_line['product_id'] = product_id
448
449         elif llave == '24':
450             # 'Pertenece a ticket cancelado'
451             if data['texto']:
452                 tck_line.update({'texto': data['texto']})
453
454         elif llave == '26':  # no se lee
455             # 'Cabezal de beneficio al total'
456             pass
457
458         elif llave == '27':  # no se lee
459             # 'Detalle de un beneficio al total'
460             pass
461
462         elif llave == '29':
463             # Es la línea de devolución de envase
464             # 'Devolución de envases'           H A R D C O D E D
465             cantidad = Decimal('1.0')
466             importe_iva = Decimal(data['iva'])
467             importe_siva = Decimal(data['precio']) * cantidad
468             importe_civa = importe_siva + importe_iva
469
470             llave_29 = dict(
471                 tipo_medio = 'Dev envase',
472                 cantidad = 1.0,
473                 importe_iva = round(importe_iva, 2),
474                 importe_siva = round(importe_siva, 2),
475                 importe_civa = round(importe_civa, 2),
476                 codigoiva = '1',
477                 codigoarticulo = '4045',  # esto es así porque no podemos identificar los envases
478                 codigooriginal = '4045',
479                 codigomediopago = 'Devol. envases'
480             )
481             logging.info(" %s [ INFO ] Devol. Envase: %s " % (ns, round(importe_civa, 2)))
482             tck_line.update(llave_29)
483
484         elif llave == '30':
485             # 'Venta a subfamilia'
486             cantidad = Decimal(data['cantidad'])
487             importe_iva = Decimal(data['iva'])
488             importe_siva = Decimal(data['precio']) * cantidad
489             importe_civa = importe_siva + importe_iva
490
491             tck_line.update(dict(
492                 cantidad = round(cantidad, 3),
493                 importe_iva = round(importe_iva, 2),
494                 importe_siva = round(importe_siva, 2),
495                 importe_civa = round(importe_civa, 2),
496                 lineacancelada = data['lineacancelada'],
497                 modoingreso = data['modoingreso'],
498                 codigoarticulo = data['codigo']
499             ))
500
501         elif llave == '37':
502             # 'Pago con tarjeta'
503
504             llave_37 = dict(
505                 tipo_medio = 'Tarjeta',
506                 codigomediopago = data['codigomediopago'],
507                 codigomoneda = data['codigomoneda'],
508                 totalmediopagomoneda = round(Decimal(data['totalmediopagomoneda']), 2),
509                 totalmediopagomonedamonedareferencia = round(Decimal(data['totalmediopagomonedamonedareferencia']),
510                                                              2),
511                 totalpagado = round(Decimal(data['totalpagado']), 2),
512                 totalpagadomonedareferencia = round(Decimal(data['totalpagadomonedareferencia']), 2),
513                 cambio = round(Decimal(data['cambio']), 2),
514                 tipooperacion = data['tipooperacion'],
515                 lineaultimopago = data['lineaultimopago'],
516                 numerotarjetacredito = data['numerotarjetacredito'],
517                 cuotastarjetacredito = data['cuotastarjetacredito'],
518                 numeroautorizaciontarjetacredito = data['numeroautorizaciontarjetacredito'],
519                 tipotarjetacredito = data['tipotarjetacredito'],
520                 autorizasupervisora = data['autorizasupervisora'],
521                 codigosupervisora = data['codigosupervisora'],
522                 lineacancelada = data['lineacancelada'],
523                 plan = data['plan'],
524                 nrocomercio = data['nrocomercio'],
525                 siaplicaleydesciva = data['siaplicaleydesciva'],
526                 montodescuentoleyiva = data['montodescuentoleyiva'],
527                 textoley = data['textoley'],
528                 siesdebitocredito = data['siesdebitocredito'],
529             )
530
531             mediosdepago['tarjetas_tck'].append(llave_37)           # mp  tarjetas_tck
532
533         elif llave == '38':
534             # 'Pago con cheque'
535
536             llave_38 = dict(
537                 medio_pago = 'cheque',
538                 codigomediopago = data['codigomediopago'],
539                 codigomoneda = data['codigomoneda'],
540                 totalmediopagomoneda = data['totalmediopagomoneda'],
541                 totalmediopagomonedamonedareferencia = data['totalmediopagomonedamonedareferencia'],
542                 totalpagado = data['totalpagado'],
543                 totalpagadomonedareferencia = data['totalpagadomonedareferencia'],
544                 cambio = data['cambio'],
545                 tipooperacion = data['tipooperacion'],
546                 lineaultimopago = data['lineaultimopago'],
547                 tipocliente = data['tipocliente'],
548                 idcliente = data['idcliente'],
549                 autorizasupervisora = data['autorizasupervisora'],
550                 codigosupervisora = data['codigosupervisora'],
551                 lineacancelada = data['lineacancelada']
552             )
553
554             mediosdepago['cheques_tck'].append(llave_38)         # mp cheques_tck
555
556         elif llave == '40':
557             # 'Pago con luncheon ticket'
558
559             llave_40 = dict(
560                 tipo_medio = 'Luncheon Ticket',
561                 codigomediopago = data['codigomediopago'],
562                 codigomoneda = data['codigomoneda'],
563                 totalmediopagomoneda = data['totalmediopagomoneda'],
564                 totalmediopagomonedamonedareferencia = data['totalmediopagomonedamonedareferencia'],
565                 totalpagado = data['totalpagado'],
566                 totalpagadomonedareferencia = data['totalpagadomonedareferencia'],
567                 cambio = data['cambio'],
568                 tipooperacion = data['tipooperacion'],
569                 lineaultimopago = data['lineaultimopago'],
570                 codigobarra = data['codigobarra'],
571                 modoingresocupon = data['modoingresocupon'],
572                 autorizasupervisora = data['autorizasupervisora'],
573                 codigosupervisora = data['codigosupervisora'],
574                 lineacancelada = data['lineacancelada']
575             )
576             print(mediosdepago.keys())
577             mediosdepago['tarjetas_tck'].append(llave_40)
578
579         elif llave == '43':
580             # 'Voucher de tarjeta'" % ns )
581             if data['tipovoucher'] == '1':  # solo la copia establecimiento.
582                 cabezal_ticket['vouchertar_tck'].append(
583                     dict(
584                         nombreemisortarjeta = data['nombreemisortarjeta'],
585                         numerotarjeta = data['numerotarjeta'],
586                         # numerotarjetacredito    = data['numerotarjeta'],
587                         vencimiento = data['vencimiento'],
588                         comprobante = data['comprobante'],
589                         autorizacion = data['autorizacion'],
590                         plan = data['plan'],
591                         cantidadcuotas = data['cantidadcuotas'],
592                         codigoterminal = data['codigoterminal'],
593                         codigocomercio = data['codigocomercio'],
594                         tipoautorizacion = data['tipoautorizacion'],
595                         nrolote = data['nrolote'],
596                         codigomoneda = data['codigomoneda'],
597                         tipotransaccion = data['tipotransaccion'],
598                         tipovoucher = data['tipovoucher'],
599                         importepago = data['importepago'],
600                         fechatransaccion = data['fechatransaccion'],
601                         codigocaja = data['codigocaja'],
602                         codigocajera = data['codigocajera'],
603                         nombrepropietario = data['nombrepropietario'],
604                         tipoingreso = data['tipoingreso'],
605                         descuentaivarestaurante = data['descuentaivarestaurante'],
606                         siesdebitocredito = data['siesdebitocredito'],
607                         cardtype = data['cardtype'],
608                         saldogift = data['saldogift'],
609                         tipotarjetacredito2 = data['tipotarjetacredito2'],
610                         descuentoafam = data['descuentoafam'],
611                         siaplicaleydesciva = data['siaplicaleydesciva'],
612                         montodescuentoleyiva = data['montodescuentoleyiva'],
613                         montoticket = data['montoticket'],
614                         montogravado = data['montogravado'],
615                         flagimprimefirma = data['flagimprimefirma']
616                         )
617                     )
618
619         elif llave == '47':
620             """
621             Línea de pago de servicio (47) -cuenta corriente, por ahora es el único que se usa-
622                 El cliente PAGA un servicios, nosotros COBRAMOS dicho servicio.
623                 Representa las líneas de los pagos de servicios .
624                 Código         -> Código del pago de servicio    # identificador de servicios a pagar / bobrar
625                 Monto          -> Importe del pago de servicio.
626                 Moneda         -> Código de moneda.
627                 ModoIngreso    -> 0-Teclado. 1-Scanner. 2-Banda magnética.
628                 CodigoVendedor -> Código de vendedor si la caja está configurado para utilizar vendedor.Si no hay 
629                                     vendedor va vacío.
630                 Referencia     -> Referencia del pago de servicio. Esta se compone de dos partes,los primeros 10 
631                                     dígitos corresponde al número de factura, los siguientes 10 dígitos al número 
632                                     de cuenta. Puede venir vacio.
633                 LineaCancelada -> 0 - Línea de pago no cancelada. 1 - Línea de pago cancelada. 
634                                         Si es uno, el ticket No tiene valor contable.
635         
636                 C#1#4#1294#131#20151218113128#F#0#15603.00#20#12                     --.
637                 L#1#5#113128#                                                          |
638                 L#3#7#113128#131#SHIRLEY BRAVO                                         |
639                 L#4#53#113128#TICKET DE VENTA#0                                        |  
640                 L#5#57#113128#20##0###                                                 |     Un ticket entero      
641                 L#6#47#113128#1#15602.83#1#0###0                                       |}    de una cobranza       
642                 L#7#68#113143#4580#ROIG ELBIO##JUAN M.GUTIERREZ 1643 -21490###1#0      |     (según salida Pazos4)
643                 L#8#4#113229#15602.83#0.00#0.00#0.00                                   |                           
644                 L#9#63#113229#15602.83#0.17#15603.00#1#1                               |
645                 L#10#9#113229#1#1#15603.00#15603.00#15603.00#15603.00#0.00#0#1#0##0   _|
646         
647                 ticket = {
648                     ('C', '1', '4', '1294', '131', '20151218113128', 'F', '0', '15603.00', '20', '12') :
649                         ['L', '1', '5', '113128', ''],
650                         ['L', '3', '7', '113128', '131', 'SHIRLEY BRAVO'],
651                         ['L', '4', '53', '113128', 'TICKET DE VENTA', '0'],
652                         ['L', '5', '57', '113128', '20', '', '0', '', '', ''],
653                     --> ['L', '6', '47', '113128', '1', '15602.83', '1', '0', '', '', '0'], <--
654                         ['L', '7', '68', '113143', '4580', 'ROIG ELBIO', '', 'JUAN M.GUTIERREZ 1643 -21490', '', '', '1', '0'],
655                         ['L', '8', '4', '113229', '15602.83', '0.00', '0.00', '0.00'],
656                         ['L', '9', '63', '113229', '15602.83', '0.17', '15603.00', '1', '1'],
657                         ['L', '10', '9', '113229', '1', '1', '15603.00', '15603.00', '15603.00', '15603.00', '0.00', '0', '1', '0', '', '0']
658                 }
659                 Ejemplo
660                 Caso línea tipo (47) del ejemplo:
661                       '1',  '15602.83',     '1',      '0',            '',             '',        '0'
662                     Código #   Monto    # Moneda # ModoIngreso # CodigoVendedor # Referencia # LineaCancelada
663                        0         1          2          3               4              5              6                  
664             """
665
666             # importe y tipo de servicio cobrado (por ahora solo cobranzas de ct.cte)
667
668             # Si la línea de cobranza no tiene código de servicio pagado, lo hardcodeamos.
669             # como si fuera cobranza de cuenta corriente '1' y el importe a 0.0
670             if 'codserviciopagado' in data:
671                 if not len(data['codserviciopagado']):
672                     data['codserviciopagado'] = '1'
673
674             if 'importecobranza' in data:
675                 if not len(data['importecobranza']):
676                     data['importecobranza'] = 0.0
677
678             # Si la 68 creó la llave con el id del ticket (cabezal) como sub-llave de 'cobranzas_tck'
679             # y cargó datos de identificación de cliente en dicha llave,
680             # entonces agregamos importe y tipo de servicio en dicha llave
681             if tck_line['tck_id'] in cabezal_ticket['cobranzas_tck']:
682                 cabezal_ticket['cobranzas_tck'][tck_line['tck_id']].update({
683                         'importecobranza': round(Decimal(data['importecobranza']), 2),
684                         'codserviciopagado': data['codserviciopagado']
685                         }
686                     )
687             else:  # Si no,
688                 # se crea la llave con el id del ticket (cabezal) como sub-llave de 'cobranzas_tck'
689                 # y se agregan los items `importe` y `tipo de servicio *cobrado*` en dicha llave """
690                 cabezal_ticket['cobranzas_tck'].update({
691                     tck_line['tck_id']: {
692                         'importecobranza': round(Decimal(data['importecobranza']), 2),
693                         'codserviciopagado': data['codserviciopagado']
694                         }
695                     })
696                 """
697                 Redefinimos el cabezal """
698                 cabezal_ticket['tipocabezal'] = 'cobranza'  # se sobreescribe la llave
699                 cabezal_ticket['descripcion_cab'] = 'Ticket de Cobranza'  # y la descripción del ticket
700
701             # TODO DIRECTO AL CABEZAL
702
703         elif llave == '52':
704             # Pago desde caja
705             cabezal_ticket['comprobantes']['egresocaja_tck'].append(
706                 dict(
707                     cantidad = 1.0,
708                     importe_siva = float(data['importe'] * -1),
709                     importe_iva = float(data['importe'] * -1),
710                     importe_civa = float(data['importe'] * -1),
711                     codigooriginal = data['codigo'],
712                     codigoarticulo = '9-pago-desde-caja'
713                     )
714                 )
715             cabezal_ticket
716         elif llave == '53':
717             # 'Tipo de ticket'
718             cabezal_ticket['tipo_de_ticket_descrip'] = data['descripciontipoticket']
719             cabezal_ticket['tipo_de_ticket_tipovta'] = data['tipoventa']
720
721         elif llave == '54':
722             # 'Pago de ticket en puntos'
723
724             llave_54 = dict(
725                 tipo_medio = 'Pago con Puntos',
726                 codigomediopago = data['codigomediopago'],
727                 codigomoneda = data['codigomoneda'],
728                 totalmediopagomoneda = round(Decimal(data['totalmediopagomoneda']), 2),
729                 totalmediopagomonedamonedareferencia = round(Decimal(data['totalmediopagomonedamonedareferencia']),
730                                                              2),
731                 totalpagado = round(Decimal(data['totalpagado']), 2),
732                 totalpagadomonedareferencia = round(Decimal(data['totalpagadomonedareferencia']), 2),
733                 cambio = round(Decimal(data['cambio']), 2),
734                 tipooperacion = data['tipooperacion'],
735                 lineaultimopago = data['lineaultimopago'],
736                 autorizasupervisora = data['autorizasupervisora'],
737                 codigosupervisora = data['codigosupervisora'],
738                 lineacancelada = data['lineacancelada']
739             )
740
741             mediosdepago['puntos_tck'].append(llave_54)
742
743         elif llave == '55':
744             # 'Intervensión Supervisora'
745             nota = "Supervisor/a %s %s" % (data['codigosuper'], data['nombresuper'])
746             tck_line.update(dict(codigoarticulo = 'interv.super.',
747                                  codigosuper = data['codigosuper'],
748                                  nombresuper = data['nombresuper'],
749                                  nota = nota))
750
751         elif llave == '57':  # no se leera
752             # Tipo de cliente    fidelización
753             pass
754             """
755             tipodecliente = dict(
756                 tipo_de_cliente    = data['tipo'],
757                 numerotarjeta      = data['numerotarjeta'],
758                 modoingreso        = data['modoingreso'],
759                 nombre             = data['nombre'],
760                 numero             = data['numero'],
761                 tipoclienteinterno = data['tipoclienteinterno']))
762             """
763
764         elif llave == '63':
765             # 'Redondeo de importe' al total de ticket
766             llave_63 = dict(
767                 tipo_medio = 'Redondeos',
768                 codigomediopago = data['codigomediopago'],  # x redondeo
769                 importeticket = round(Decimal(data['importeticket']), 2),
770                 importeredondeo = round(Decimal(data['importeredondeo']), 2),
771                 importetotalticket = round(Decimal(data['importetotalticket']), 2),
772                 codigomoneda = data['codigomoneda']
773                 )
774             mediosdepago['redondeos_tck'].append(llave_63)
775
776         elif llave == '68':
777             """
778                 Entrega a domicilio  
779                 lo usamos IDENTIFICACION de cliente de COBRANZA.
780                 Atención: Si se habilita cobranza "dentro del ticket" de compra esto no funcionará.
781                           No podremos sobreescribir el tipo de ticket(cabezal) ni su descripción!!
782             """
783             #  Sí hay codigo y noombre de cliente se cargan, sinó se inventan
784             if 'codigocliente' in data and len(data['codigocliente'].strip()):
785                 codigocliente = data['codigocliente'].strip()
786             else:
787                 codigocliente = 'Sin codigo de cliente'
788                 logging.info(" %s [ WARNING ] : %s " % (ns, codigocliente))
789
790             if 'nombrecliente' in data and len(data['nombrecliente'].strip()):
791                 nombrecliente = data['nombrecliente']
792             else:
793                 nombrecliente = 'Sin nombre de cliente'
794                 logging.info(" %s [ WARNING ] : %s " % (ns, nombrecliente))
795
796             # sí el 48 creó la llave `tck_line['tck_id']` en `cabezal_ticket['cobranzas_tck']`
797             # cargó importe y tipo de servicio cobrado. Entonces cargamos la
798             # identificación del cliente dicha llave
799             if tck_line['tck_id'] in cabezal_ticket['cobranzas_tck']:
800                 cabezal_ticket['cobranzas_tck'][tck_line['tck_id']].update(
801                     dict(codigocliente = codigocliente, nombrecliente = nombrecliente)
802                     )
803             else:  # si la 47 no cargó nada
804                 # Entonces cramaos la llave y le cargamos la identificación del cliente
805                 cabezal_ticket['cobranzas_tck'].update({
806                     tck_line['tck_id']: dict(codigocliente = codigocliente, nombrecliente = nombrecliente)}
807                     )
808                 # Finalmente redefinimos el ticket
809                 cabezal_ticket['tipocabezal'] = 'cobranza'                # Sobreescribimos el tipo de cabezal
810                 cabezal_ticket['descripcion_cab'] = 'Ticket de Cobranza'  # y la descripción del mismo.
811
812         elif llave == '81':
813             """                    
814                 Devolución de un pago de servicio. (COBRANZA)
815
816                 IdentificadorLinea # NumeroDeLinea # TipoLinea # TimestampLinea #
817         
818                 Código # Importe # Moneda # ModoIngreso # CodigoSupervisora # CodigoVendedor #
819                    0        1        2           3              4                   5
820                 Referencia # LineaCancelada
821                     6              7
822         
823                 Código      ->  Código del pago de servicio
824                 Importe     ->  Importe de la devolución del pago de servicio (en negativo).
825                 Moneda      ->  Código de moneda.
826                 ModoIngreso ->  0-Teclado
827                                 1-Scanner.
828                                 2-Banda magnética.
829                 CodigoSupervisora   ->  Código de la supervisora si intervino, sino va vacío.
830                 CodigoVendedor      ->  Código de vendedor si la caja está configurado para utilizar
831                                         vendedor. Si no hay vendedor va vacío.
832                 Referencia          ->  Referencia del pago de servicio.
833                 LineaCancelada      ->  0-Línea de devolucion de pago de servicio no cancelada.
834                                         1-Línea de devolucion de pago de servicio cancelada.
835                                         No se deberia tomar en cuenta como valor contable.
836         
837                 Ejemplo de la devolucion del servicio 513 por -250.00 de la moneda 1, ingresado por
838                 teclado (0) e intervino la supervisora 1, sin vendedor ni referencia y la línea no esta
839                 canclada (0).
840                 L#7#81#122220#513#-250.00#1#0#1###0                            
841             """
842             #  si la línea de devol cobranza no tiene código de servicio pagado, lo hardcodeamos
843             if 'codigo' in data and not data['codigo']:
844                 data['codigo'] = '1'
845             data['codserviciopagado'] = data['codigo']
846
847             if 'importe' in data:
848                 data['importecobranza'] = data['importe']
849             llave_81 = {
850                  'importecobranza': round(Decimal(data['importecobranza']), 2),
851                  'codserviciopagado': data['codserviciopagado'],
852                  'codigosupervisora': data['codigosupervisora'],
853                 }
854             lineas2cabezal['cobranzas_tck'].append(llave_81)
855
856             cabezal_ticket['note'] += "\nReferencia: " + data['referencia'] + "Linea Cancelada: " + data[
857                 'lineacancelada']
858
859             cabezal_ticket['tipocabezal'] = 'cobranza'
860             cabezal_ticket['hay_cobza'] = True
861             cabezal_ticket['descripcion_cab'] = 'Devolución de Cobranza'
862
863         elif llave == '82':
864             """ Línea de consulta de estado de cuenta de la cobranza (82).
865                 Representa a las líneas de información que contienen la consulta del estado de cuenta de
866                 un cliente con respecto a una Cobranza Online.
867             """
868             pass
869         elif llave == '83':
870             pass
871             """ 
872             No lo usamos, no tenemos esa cobranza.
873             Línea de voucher de la cobranza (83). De TARJETA de CRÉDITO
874             Representa el vocucher de un pago/devolución de tarjeta de crédito.
875             La mayoría de la información aquí presentada la retorna el autorizador y Jswitch
876             (referirse al documento Especificaciones jSwitch.doc por posibles cambios).
877
878             Descripcion # NumeroTarjeta # NumeroCuenta # Vencimiento # Autorizacion #
879                  0              1               2             3             4       
880             TipoAutorizacion # CodigoMoneda # Importe # TipoVoucher # TipoCobranza #
881                     5                6           7           8             9
882             IndicadorPagoDev
883                     10
884
885             NumeroCuenta->Numero de cuenta del cliente (cuando la cobranza se hace offline, si es
886             online puede venir vacio).
887             *Datos que no provienen de la autorizadora.
888
889             Ejemplo del voucher de cobranza VISA con numero de tarjeta 5898920239862737 sin
890             numero de cuenta con vencimineto 0705 , autorizacion 000000 que se hizo online (00)
891             con importe de 250.00 pesos (00), es la via del cliente (0) , se selecciono online (1) y
892             es un pago (0).
893             L#11#83#183404#VISA#5898920239862737##0705#000000#00#00#250.00#0#1#0
894
895             Idem para el establecimiento (1):
896             L#12#83#183404#VISA#5898920239862737##0705#000000#00#00#250.00#1#1#0
897             #  #####################
898             llave_83 = dict(
899                         descripcion      = data['descripcion'],
900                         numerotarjeta    = data['numerotarjeta'],
901                         numerocuenta     = data['numerocuenta'],
902                         vencimiento      = data['vencimiento'],
903                         autorizacion     = data['autorizacion'],
904                         tipoautorizacion = data['tipoautorizacion'],
905                         codigomoneda     = data['codigomoneda'],
906                         importe          = data['importe'],
907                         tipovoucher      = data['tipovoucher'],
908                         tipocobranza     = data['tipocobranza'],
909                         indicadorpagodev = data['indicadorpagodev']
910             )
911             """
912         elif llave == '84':
913             """ No hay Línea de apertura de gaveta (84).
914                 Representa la línea de apertura de gaveta que hace la cajera de forma expresa con la
915                 tecla de función correspondiente (en este momento esta en el menú de cierre de caja).En
916                 si el dato relevante es el tipo de línea para contabilizar cuantas aperturas de gaveta hizo
917                 la cajera.
918             """
919             tck_line.update(dict(descripcion = data['descripcion']))
920
921         elif llave == '85':
922             # 'Pago de tarjeta offline'
923             llave_85 = dict(
924                 tipo_medio = 'Tarjeta off line',
925                 codigomediopago = data['codigomediopago'],
926                 codigomoneda = data['codigomoneda'],
927                 totalmediopagomoneda = round(Decimal(data['totalmediopagomoneda']), 2),
928                 totalmediopagomonedamonedareferencia = round(Decimal(data['totalmediopagomonedamonedareferencia']),
929                                                              2),
930                 totalpagado = round(Decimal(data['totalpagado']), 2),
931                 totalpagadomonedareferencia = round(Decimal(data['totalpagadomonedareferencia']), 2),
932                 cambio = round(Decimal(data['cambio']), 2),
933                 tipooperacion = data['tipooperacion'],
934                 lineaultimopago = data['lineaultimopago'],
935                 numerotarjetacredito = data['numerotarjetacredito'],
936                 autorizasupervisora = data['autorizasupervisora'],
937                 codigosupervisora = data['codigosupervisora'],
938                 lineacancelada = data['lineacancelada']
939             )
940
941             mediosdepago['tarjetas_tck'].append(llave_85)            # mp tarjetas_tck offline
942
943         elif llave == '90':
944             # 'Pago ticket TAlimentos
945
946             llave_90 = dict(
947                 tipo_medio = 'Ticket Alimentos',
948                 codigomediopago = data['codigomediopago'],
949                 codigomoneda = data['codigomoneda'],
950                 totalmediopagomoneda = round(Decimal(data['totalmediopagomoneda']), 2),
951                 totalmediopagomonedamonedareferencia = round(Decimal(data['totalmediopagomonedamonedareferencia']),
952                                                              2),
953                 totalpagado = round(Decimal(data['totalpagado']), 2),
954                 totalpagadomonedareferencia = round(Decimal(data['totalpagadomonedareferencia']), 2),
955                 cambio = round(Decimal(data['cambio']), 2),
956                 tipooperacion = data['tipooperacion'],
957                 lineaultimopago = data['lineaultimopago'],
958                 codigobarra = data['codigobarra'],
959                 modoingresocupon = data['modoingresocupon'],
960                 autorizasupervisora = data['autorizasupervisora'],
961                 codigosupervisora = data['codigosupervisora'],
962                 lineacancelada = data['lineacancelada']
963             )
964
965             mediosdepago['tarjetas_tck'].append(llave_90)
966
967         elif llave == '91':
968
969             # 'Pago con Tticket Total'
970
971             llave_91 = dict(
972                 tipo_medio = 'Ticket Ttotal',
973                 codigomediopago = data['codigomediopago'],
974                 codigomoneda = data['codigomoneda'],
975                 totalmediopagomoneda = round(Decimal(data['totalmediopagomoneda']), 2),
976                 totalmediopagomonedamonedareferencia = round(Decimal(data['totalmediopagomonedamonedareferencia']),
977                                                              2),
978                 totalpagado = round(Decimal(data['totalpagado']), 2),
979                 totalpagadomonedareferencia = round(Decimal(data['totalpagadomonedareferencia']), 2),
980                 cambio = round(Decimal(data['cambio']), 2),
981                 tipooperacion = data['tipooperacion'],
982                 lineaultimopago = data['lineaultimopago'],
983                 codigobarra = data['codigobarra'],
984                 modoingresocupon = data['modoingresocupon'],
985                 autorizasupervisora = data['autorizasupervisora'],
986                 codigosupervisora = data['codigosupervisora'],
987                 lineacancelada = data['lineacancelada'],
988                 nombretarjeta = 'TICKET TOTAL'
989             )
990
991             mediosdepago['tarjetas_tck'].append(llave_91)            # mp tarjetas_tck T.Total
992
993         elif llave == '92':  # no
994             # 'Emisión de factura'
995             pass
996
997         elif llave == '97':  # no
998
999             llave_97 = dict(
1000                 tipo_medio = 'Retiro de Caja',
1001                 codigomediopago = data['codigomediopago'],
1002                 codigomoneda = data['codigomediopago'],
1003                 montoretiro = round(Decimal(data['montoretiro']), 2),
1004                 nota = "Retiro de caja | codigomediopago : %s, codigomoneda : %s, montoretiro : %s " % \
1005                        (data['codigomediopago'], data['codigomoneda'], data['montoretiro']), )
1006
1007             lineas2cabezal['retiros_tck'].append(llave_97)
1008
1009         elif llave == '106':  # no
1010             # 'Cliente facturacion'
1011             pass
1012
1013         elif llave == '109':  # no
1014             # Devolución gift card (109)                      109
1015             pass
1016
1017         elif llave == '115':  # no
1018             # 'Pago descuento Iva Afam'
1019             pass
1020
1021         elif llave == '117':
1022             # Preventa
1023             pass
1024
1025         elif llave == '118':
1026             """
1027                 Línea de ticket vale almuerzo (118)-SM
1028                 Línea de ticket de identificación del empleado que va a utilizar el vale almuerzo.
1029
1030                 IdentificadorLinea # NumeroDeLinea # TipoLinea # TimestampLinea #
1031                 FlagTarjetaDocumento # TipoDocumento # NumeroDocumento # ModoIngreso #
1032                 Track1 # Track2 # NumeroTarjeta # ModoValeAlmuerzo # AcumuladoDiasSemana
1033
1034                 FlagTarjetaDocumento->Indicador si se trata de tarjeta o documento como dato
1035                 identificatorio.
1036                 0-Tarjeta.
1037                 1-Documento
1038                 TipoDocumento-> Tipo de documento si FlagTarjetaDocumento=1, sino va vacío.
1039                 C-Cédula de identidad.
1040                 O-Otro.
1041                 NumeroDocumento-> Número de documento si FlagTarjetaDocumento=1, sino va
1042                 vacío.El número de documento tiene concatenado el tipo de documento (primer
1043                 carácter).
1044                 ModoIngreso-> Modo de ingreso de la Tarjeta/Documento:
1045                 0-Teclado.
1046                 1-Scanner.
1047                 2-Lectora de banda magnética.
1048                 Track1-> Track 1 de la tarjeta si FlagTarjetaDocumento=0.Puede venir vacío.
1049                 Track2-> Track 2 de la tarjeta si FlagTarjetaDocumento=0.Puede venir vacío.
1050                 NumeroTarjeta-> Numero de la tarjeta si FlagTarjetaDocumento=0.Puede venir vacío.
1051                 ModoValeAlmuerzo->D-Diario-El vale almuerzo se puede aplicar todos los dias de la
1052                 semana (aplicando el descuento correspondiente por dia).
1053                 S-Semanal-El vale almuerzo se aplica en su totalidad una vez a la
1054                 semana (aplicando el descuento acumulado una vez a la semana).
1055                 Dicho descuento depende de AcumuladoDiasSemana.
1056                 AcumuladoDiasSemana->Acumulado de dias trabajados en la semana para aplicar el
1057                 descuento si es semanal.
1058                 Ejemplo de identificación de un vale almuerzo de tipo tarjeta (0) que se ingresó por la
1059                 lectora de banda magnetica (2), el valor del track 2 es 1032240472=0000 ,el numero de
1060                 tarjeta es 1032240472, el modo de vale almuerzo es semanal (S) y lo acumulado de dias
1061                 a la semana de trabajo es 6.
1062                 L#6#118#180726#0###2##1032240472=0000#1032240472#S#6
1063                 Ejemplo de identificación de un vale almuerzo de tipo documento (1) con tipo de
1064                 documento Otro (O), numero de documento O12345678 (el documento real seria
1065                 12345678 ya que el primer carácter tambien identifica el tipo de documento) y se
1066                 ingresó por teclado (0).
1067                 L#6#118#170035#1#O#O12345678#0###
1068             """
1069             #  identificación del empleado que va a utilizar el vale almuerzo
1070             llave_118 = dict(
1071                         flagtarjetadocumento = data['flagtarjetadocumento'],
1072                         tipodocumento = data['flagtarjetadocumento'],
1073                         numerodocumento = data['numerodocumento'],
1074                         modoingreso = data['modoingreso'],
1075                         track1 = data['track1'],
1076                         track2 = data['track2'],
1077                         numerotarjeta = data['numerotarjeta'],
1078                         modovalealmuerzo = data['modovalealmuerzo'],
1079                         acumuladodiassemana = data['acumuladodiassemana'])
1080
1081         elif llave == '119':
1082             """
1083             Línea de ticket pago vale almuerzo (119)-SM
1084             ===========================================
1085             Es identica a la línea de pago de efectivo (9) solo que se
1086             distingue por el codigo medio de pago y moneda.
1087
1088             Línea de pago de ticket en efectivo (9).
1089             ---------------------------------------
1090
1091             CodigoMedioPago # CodigoMoneda # TotalMedioPagoMoneda #
1092                 0                1                 2
1093
1094             TotalMedioPagoMonedaMonedaReferencia # TotalPagado #
1095                         3                               4
1096
1097             TotalPagadoMonedaReferencia # Cambio # TipoOperacion # LineaUltimoPago #
1098                         5                    6          7                8
1099
1100             AutorizaSupervisora # CodigoSupervisora # LineaCancelada
1101                     9                    10                11
1102
1103             0. Código del medio de pago.
1104             1. Código de la moneda.
1105             2. Monto total de lo que se puede pagar con el medio de pago moneda.
1106             3. Idem que el anterior pero expresado en la moneda de referencia.
1107             4. Total entregado de ese medio de pago-moneda.
1108             5. Total entregado expresado en la moneda de referencia.
1109             6. Cambio de la línea de pago (valor >= 0.00)
1110             7. Codigo de Operacion.
1111                     0 - Si corresponde a una venta (los importes van en positivo).
1112                     1 - Si corresponde a una devolución por parte del cliente (los
1113                         importes van en negativo).
1114             8. Ultimo pago.
1115                     0 - No es la línea del último pago. Esto sucede cuando el ticket
1116                         se paga con múltiples pagos (inclusive de distintos medios
1117                         de pago-monedas) cuando el importe abonado es menor al
1118                         total a pagar.
1119                     1 - Es la línea del último pago.
1120             9. Intervención supervisor.
1121                     0 - Línea de pago sin intervención de supervisor.
1122                     1 - Línea de pago autorizada por supervidor.
1123             10. Código de la supervisora.
1124             11. Estado de la línea de pago.
1125                 0-Línea de pago no cancelada.
1126                 1-Línea de pago cancelada.
1127             """
1128             try:
1129
1130                 llave_119 = dict(
1131                     tipo_medio = 'Ticket Almuerzo',
1132                     codigomediopago = data['codigomediopago'],
1133                     codigomoneda = data['codigomoneda'],
1134                     totalmediopagomoneda = round(Decimal(data['totalmediopagomoneda']), 2),
1135                     totalmediopagomonedamonedareferencia = round(
1136                         Decimal(data['totalmediopagomonedamonedareferencia']), 2),
1137                     totalpagado = round(Decimal(data['totalpagado']), 2),
1138                     totalpagadomonedareferencia = round(Decimal(data['totalpagadomonedareferencia']), 2),
1139                     cambio = round(Decimal(data['cambio']), 2),
1140                     tipooperacion = data['tipooperacion'],
1141                     lineaultimopago = data['lineaultimopago'],
1142                     autorizasupervisora = data['autorizasupervisora'],
1143                     codigosupervisora = data['codigosupervisora'],
1144                     lineacancelada = data['lineacancelada']
1145                 )
1146                 if llave_118:
1147                     llave_119.update({'note': llave_118})
1148                     llave_118 = None
1149                 mediosdepago['tarjetas_tck'] = llave_119
1150
1151             except Exception as ex:
1152                 verbose = 1
1153                 msg = "[ERROR]: %s %s %s" % (ex, llave, cabezal_ticket['descripcion_cab'])
1154                 frame = insp.getframeinfo(insp.currentframe()) if verbose else False
1155                 excepcion(msg, frame, cabezal_ticket)
1156
1157         elif llave == '120':
1158             # identificador de línea / operación
1159             # import ipdb;ipdb.set_trace()
1160             llave_120 = [{'id': data['ventamides'] + ' CI :' + data['ci']}]
1161             mediosdepago['mides_tck'].append(llave_120)
1162
1163         elif llave == '121':  # no
1164             # 'Voucher retiro leche tarjeta Mides'
1165             pass  # print data
1166
1167         elif llave == '123':
1168             """
1169                 Línea de pago TACRE (123)-SM / (126) P4 (no CFE).
1170                 Representa la línea de pago por Tarjeta Ticket Alimentacion/Canasta/Restaurante de
1171                 forma electrónica.
1172             """
1173             try:
1174
1175                 llave_123 = dict(
1176                     tipo_medio = 'TACRE',
1177                     codigomediopago = data['codigomediopago'],
1178                     codigomoneda = data['codigomoneda'],
1179                     totalmediopagomoneda = round(Decimal(data['totalmediopagomoneda']), 2),
1180                     totalmediopagomonedamonedareferencia = round(
1181                         Decimal(data['totalmediopagomonedamonedareferencia']), 2),
1182                     totalpagado = round(Decimal(data['totalpagado']), 2),
1183                     totalpagadomonedareferencia = round(Decimal(data['totalpagadomonedareferencia']), 2),
1184                     cambio = round(Decimal(data['cambio']), 2),
1185                     tipooperacion = data['tipooperacion'],
1186                     lineaultimopago = data['lineaultimopago'],
1187                     numerotarjeta = data['numerotarjeta'],
1188                     numerotarjetacredito = data['numerotarjeta'],
1189                     numeroautorizacion = data['numeroautorizacion'],
1190                     numeroautorizaciontarjetacredito = data['numeroautorizacion'],
1191                     autorizasupervisora = data['autorizasupervisora'],
1192                     codigosupervisora = data['codigosupervisora'],
1193                     lineacancelada = data['lineacancelada'],
1194                     siaplicaleydesciva = data['siaplicaleydesciva'],
1195                     montodescuentoleyiva = data['montodescuentoleyiva'],
1196                     textoley = data['textoley'],
1197                     )
1198
1199                 mediosdepago['tacrt_tck'].append(llave_123)
1200                 # Tar T.Alim./Canasta/Restaurante Elect. de forma electrónica.
1201                 tacre123_id = data['numerotarjeta'] + data['numeroautorizacion']
1202
1203             except Exception as ex:
1204                 verbose = 1
1205                 msg = "[ERROR]: %s %s %s" % (ex, llave, cabezal_ticket['descripcion_cab'])
1206                 frame = insp.getframeinfo(insp.currentframe()) if verbose else False
1207                 excepcion(msg, frame, cabezal_ticket)
1208
1209         elif llave == '124':
1210
1211             # Línea de voucher de la tarjeta TACRE   SODEXO/EDENRED/RADPAGOS ALIMENTOS
1212
1213             """
1214                 Línea de voucher de la tarjeta TACRE (124)-SM
1215                 =============================================
1216
1217                 Muestran la información de un Voucher de pago por Tarjeta Ticket
1218                 Alimentacion/Canasta/Restaurante de forma electronica.
1219
1220                  0. NumeroTarjeta    -> Número de la tarjeta.
1221                  1. Vencimiento      -> Vencimiento de la tarjeta (aamm).
1222                  2. Comprobante      -> Número de comprobante.
1223                  3. Autorizacion     -> Número de autorización.
1224                  4. CodigoTerminal   -> Código de la terminal asociado.
1225                  5. CodigoComercio   -> Código de comercio asociado.
1226
1227                     0               1             2             3               4
1228                NumeroTarjeta # Vencimiento # Comprobante # Autorizacion # CodigoTerminal #
1229                     5                   6             7          8                9
1230                CodigoComercio # TipoAutorizacion # NroLote # CodigoMoneda # TipoTransaccion #
1231                    10            11                 12             13           14
1232                TipoVoucher # ImportePago # FechaTransaccion # CodigoCaja # CodigoCajera #
1233                     15                  16             17            18
1234                NombrePropietario # TipoIngreso # DescuentaIva # SiAplicaLeyDescIva #
1235                         19                 20                21          22               23
1236                MontoDescuentoLeyIva # MontoFactura # MontoGravado # NombreTarjeta # FlagImprimeFirma
1237
1238             """  # ########################         llave == '124'
1239             tipo = ''
1240             if data['tipovoucher'] == "1":  # solo copia establecimiento
1241                 if data['nombretarjeta'] == 'SODEXO':
1242                     tipo = '11'
1243                 elif data['nombretarjeta'] == 'EDENRED':
1244                     tipo = '12'
1245                 elif data['nombretarjeta'] == 'REDPAGOS ALIMENTOS':
1246                     tipo = '002'
1247
1248                 llave_124 = dict(
1249                         tipo_medio = 'TACRE' + ' ' + tipo,
1250                         numerotarjeta = data['numerotarjeta'],
1251                         vencimiento = data['vencimiento'],
1252                         comprobante = data['comprobante'],
1253                         autorizacion = data['autorizacion'],
1254                         codigoterminal = data['codigoterminal'],
1255                         codigocomercio = data['codigocomercio'],
1256                         tipoautorizacion = data['tipoautorizacion'],
1257                         nrolote = data['nrolote'],
1258                         codigomoneda = data['codigomoneda'],
1259                         tipotransaccion = data['tipotransaccion'],
1260                         tipovoucher = data['tipovoucher'],
1261                         importepago = round(Decimal(data['importepago']), 2),
1262                         fechatransaccion = data['fechatransaccion'],
1263                         codigocaja = data['codigocaja'],
1264                         codigocajera = data['codigocajera'],
1265                         nombrepropietario = data['nombrepropietario'],
1266                         tipoingreso = data['tipoingreso'],
1267                         # descuentaiva = data['descuentaiva'],
1268                         descuentaivarestaurante = data['descuentaiva'],
1269                         siaplicaleydesciva = data['siaplicaleydesciva'],
1270                         montodescuentoleyiva = round(Decimal(data['montodescuentoleyiva']), 2),
1271                         # montofactura = round(Decimal(data['montofactura']),2),
1272                         montoticket = round(Decimal(data['montofactura']), 2),
1273                         montogravado = round(Decimal(data['montogravado']), 2),
1274                         nombretarjeta = data['nombretarjeta'],
1275                         nombreemisortarjeta = data['nombretarjeta'],
1276                         flagimprimefirma = data['flagimprimefirma'])
1277
1278                 tacre124_id = (data['numerotarjeta'] + data['autorizacion'], data['nombretarjeta'])
1279                 # print tacre124_id[0], tacre124_id, tacre124_id[1]
1280                 if tacre123_id and tacre123_id == tacre124_id[0]:
1281                     # import ipdb; ipdb.set_trace()
1282                     if 'numerotarjetacredito' in llave_123 and 'numeroautorizaciontarjetacredito' in llave_123:
1283                         if llave_123['numerotarjetacredito'] == data['numerotarjeta'] and \
1284                                 llave_123['numeroautorizaciontarjetacredito'] == data['autorizacion']:
1285                             llave_124['tipotarjetacredito'] = tipo
1286
1287                 cabezal_ticket['vouchertar_tck'].append(llave_124)
1288
1289                 # tarjeta TACRE   SODEXO/EDENRED/RADPAGOS ALIMENTOS
1290                 del llave_123
1291
1292         elif llave == '125':
1293             pass
1294
1295         elif llave == '126':
1296             # Línea de ticket de cliente de cuenta corriente  (126)-SM.
1297             # Datos de indetificación cliente
1298             # identificación / monto para auxiliar
1299             # 'Cliente de cuenta corriente SM' (cuando compra)  Línea de ticket de cliente de cuenta corriente (99)-P4 / (126)-SM.
1300
1301             # mediosdepago_cabezal['cuentas_tck'].append(dict(codigocc = data['codigocc'].strip() or 'no-codecc',
1302             #                                                nombrecc = data['nombrecc'] or 'no-namecc',
1303             #                                                montopagocc = data['montopagocc'] or 0.0, ))
1304
1305             llave_126 = dict(codigocc = data['codigocc'].strip() or 'no-codigocc',
1306                              nombrecc = data['nombrecc'] or 'no-nombrecc',
1307                              montopagocc = data['montopagocc'] or 0.001, )
1308
1309             # mediosdepago['cuentas_tck'].append(llave_126)
1310
1311         elif llave == '127':
1312             # Medio de pago Cuenta Corriente 127
1313
1314             '''
1315             Línea de pago cuenta corriente (104)-P4 / (127)-SM
1316             Línea del Mpdo de pago Cuenta Corriente.
1317             Es igual a la línea de pago en efectivo (9), solo que se refiere al codigo de medio de
1318             pago cuenta corriente y moneda pesos.
1319             Ejemplo:
1320             Pago de medio de pago cuenta corriente (19) efectivo (1) por 213.00.
1321             L#9#104#162055#19#1#213.00#213.00#213.00#213.00#0.00#0#1#0##0  '''
1322
1323             llave_127 = dict(
1324
1325                 tipo_medio = 'Cuentas',
1326                 codigomediopago = data['codigomediopago'],
1327                 codigomoneda = data['codigomoneda'],
1328                 totalmediopagomoneda = round(Decimal(data['totalmediopagomoneda']), 2),
1329                 totalmediopagomonedamonedareferencia = round(Decimal(data['totalmediopagomonedamonedareferencia']),
1330                                                              2),
1331                 totalpagado = round(Decimal(data['totalpagado']), 2),
1332                 totalpagadomonedareferencia = round(Decimal(data['totalpagadomonedareferencia']), 2),
1333
1334                 cambio = round(Decimal(data['cambio']), 2),
1335                 tipooperacion = data['tipooperacion'],
1336                 lineaultimopago = data['lineaultimopago'],
1337                 autorizasupervisora = data['autorizasupervisora'],
1338                 codigosupervisora = data['codigosupervisora'],
1339                 lineacancelada = data['lineacancelada']
1340             )
1341             # Agrega identificacion de cliente.
1342             if llave_126:
1343                 llave_127.update(llave_126)
1344             else:
1345                 llave_127.update(dict(codigocc = 'no-codigocc',
1346                                       nombrecc = 'no-nombrecc',
1347                                       montopagocc = 0.001))
1348             mediosdepago['cuentas_tck'].append(llave_127)
1349             llave_126 = {}
1350
1351         elif llave == '128':
1352             # 'Pago de ticket en Dev.Envases.'
1353
1354             llave_128 = dict(
1355                 tipo_medio = 'Dto. Dev envase',
1356                 codigomediopago = data['codigomediopago'],
1357                 codigomoneda = data['codigomoneda'],
1358                 totalmediopagomoneda = round(Decimal(data['totalmediopagomoneda']), 2),
1359                 totalmediopagomonedamonedareferencia = round(Decimal(data['totalmediopagomonedamonedareferencia']),
1360                                                              2),
1361                 totalpagadomonedareferencia = round(Decimal(data['totalpagadomonedareferencia']), 2),
1362                 totalpagado = round(Decimal(data['totalpagado']), 2),
1363                 cambio = round(Decimal(data['cambio']), 2),
1364                 tipooperacion = data['tipooperacion'],
1365                 lineaultimopago = data['lineaultimopago'],
1366                 autorizasupervisora = data['autorizasupervisora'],
1367                 codigosupervisora = data['codigosupervisora'],
1368                 lineacancelada = data['lineacancelada']
1369             )
1370             # print 'Mpago Envase 128 ->', llave_128
1371
1372             mediosdepago['devenvases_tck'].append(llave_128) # mp devenvses_tck
1373
1374         else:
1375             print "Llave no capturada en el if elif (acas)"
1376             print("Llave: %s \tData: %s \n\t Queda por ver `lin`." % (llave, data))
1377             import ipdb
1378             ipdb.set_trace()
1379             print("es solo para poder ver la línea díscola. `lin`... "
1380                   "Debería seguir normalmente o loguear y seguir")
1381
1382         if llave in config.linea_linea and tck_line:
1383             res.append(tck_line)
1384
1385     cabezal_ticket['lineascabezal'] = dict()
1386     cabezal_ticket['mediosdepago'] = dict()
1387     if path.isfile("/tmp/stop"):
1388         import ipdb
1389         ipdb.set_trace()
1390
1391     for i in lineas2cabezal:
1392         if lineas2cabezal[i]:
1393             cabezal_ticket['lineascabezal'].update({i: lineas2cabezal[i]})
1394
1395     for i in mediosdepago:
1396         if mediosdepago[i]:
1397             cabezal_ticket['mediosdepago'].update({i: mediosdepago[i]})
1398
1399     return res
1400
1401 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: