#!/usr/bin/python # -*- coding: utf-8 -*- "Aplicativo Visual (Front-end) Remito Electrónico (COT) ARBA" from __future__ import with_statement __author__ = "Mariano Reingart (reingart@gmail.com)" __copyright__ = "Copyright (C) 2013- Mariano Reingart" __license__ = "LGPL 3.0" import datetime import decimal import time import os import fnmatch import shelve import sys # importar gui2py (atajos) import gui # establecer la configuración regional por defecto: import wx, locale if sys.platform == "win32": locale.setlocale(locale.LC_ALL, 'Spanish_Argentina.1252') elif sys.platform == "linux2": locale.setlocale(locale.LC_ALL, 'es_AR.utf8') loc = wx.Locale(wx.LANGUAGE_DEFAULT, wx.LOCALE_LOAD_DEFAULT) # importar el módulo principal de pyafipws para remito electrónico: from cot import COT # --- here goes your event handlers --- # --- gui2py designer generated code starts --- with gui.Window(name='mywin', title=u'COT: Remito Electr\xf3nico ARBA', resizable=True, height='450px', left='180', top='24', width='550px', bgcolor=u'#E0E0E0', fgcolor=u'#4C4C4C', image='', ): gui.StatusBar(name='statusbar', ) with gui.Panel(label=u'', name='panel', image='', ): gui.TextBox(name='usuario', left='299', top='10', width='105', value=u'20267565393', ) gui.TextBox(name='clave', password=True, left='455', top='10', width='75', ) gui.Line(name='line_25_556', height='3', left='24', top='390', width='499', ) gui.Button(label=u'Salir', name='salir', left='440', top='394', width='85', onclick='import sys; sys.exit(0)', ) gui.ComboBox(name=u'url', text=u'http://cot.test.arba.gov.ar/TransporteBienes/SeguridadCliente/presentarRemitos.do', height='29', left='79', top='42', width='250', bgcolor=u'#FFFFFF', data_selection=u'http://cot.test.arba.gov.ar/TransporteBienes/SeguridadCliente/presentarRemitos.do', fgcolor=u'#4C4C4C', items=[u'https://cot.arba.gov.ar/TransporteBienes/SeguridadCliente/presentarRemitos.do', u'http://cot.test.arba.gov.ar/TransporteBienes/SeguridadCliente/presentarRemitos.do'], selection=1, string_selection=u'http://cot.test.arba.gov.ar/TransporteBienes/SeguridadCliente/presentarRemitos.do', ) gui.Label(name='lblTest_273_363', height='17', left='234', top='15', width='58', text=u'Usuario:', ) gui.Label(name='lblTest_273', height='17', left='410', top='14', width='58', text=u'Clave:', ) gui.Gauge(name='gauge', height='18', left='20', top='365', width='507', ) gui.Label(id=228, name='lblTest_228', height='17', left='341', top='47', width='32', text=u'Carpeta:', ) with gui.ListView(id=213, name=u'remitos', height='74', left='20', top='180', width='510', item_count=0, sort_column=0, ): gui.ListColumn(name=u'nro', text=u'N\xb0 \xdanico Remito', width=250, ) gui.ListColumn(name=u'proc', text=u'Procesado', ) with gui.ListView(name=u'archivos', height='99', left='21', top='77', width='509', item_count=0, sort_column=2, ): gui.ListColumn(name=u'txt', text='Archivo TXT', width=200, ) gui.ListColumn(name=u'xml', text='Archivo XML', ) gui.ListColumn(name=u'cuit', text='CUIT Empresa', ) gui.ListColumn(name=u'nro', text=u'N\xb0 Comprobante', ) gui.ListColumn(name=u'md5', text=u'C\xf3digo Integridad', ) with gui.ListView(id=309, name=u'errores', height='99', left='20', top='259', width='510', item_count=0, sort_column=0, ): gui.ListColumn(name=u'codigo', text=u'C\xf3digo', width=100, ) gui.ListColumn(name=u'descripcion', text=u'Descripci\xf3n Error', width=400, ) gui.TextBox(id=488, mask='date', name='fecha', left='101', top='10', width='127', enabled=False, value=datetime.date(2014, 4, 5), ) gui.CheckBox(label=u'Fecha:', name=u'filtrar_fecha', height='24', left='22', top='11', width='73', tooltip=u'filtrar por fecha', ) gui.Label(id=2084, name='lblTest_228_2084', height='17', left='24', top='47', width='32', text=u'URL:', ) gui.ComboBox(id=961, name=u'carpeta', text=u'datos', height='29', left='412', top='42', width='118', bgcolor=u'#FFFFFF', data_selection=u'datos', fgcolor=u'#4C4C4C', items=[u'datos', u'procesados'], selection=0, string_selection=u'datos', ) gui.Button(label=u'Procesar', name=u'procesar', left='20', top='394', tooltip="Presentar el remito en ARBA", width='85', default=True, fgcolor=u'#4C4C4C', ) gui.Button(label=u'Mover Procesados', name=u'mover', left='112', top='394', width='166', fgcolor=u'#4C4C4C', ) # --- gui2py designer generated code ends --- # get a reference to the Top Level Window (used by designer / events handlers): mywin = gui.get("mywin") panel = mywin['panel'] # Manejo simple de claves: passwd_db = shelve.open("passwd") def getpass(username): password = passwd_db.get(str(username)) if not password: password = gui.prompt(message=u"Ingrese contraseña", title="Usuario: %s" % username, password=True) or "" return password def setpass(username, password): passwd_db[str(username)] = password def grabar_clave(evt): setpass(panel['usuario'].value, panel['clave'].value) # asignar controladores cot = COT() def listar_archivos(evt=None): # cargar listado de archivos a procesar (y su correspondiente respuesta): lv = panel['archivos'] lv.clear() panel['remitos'].clear() panel['errores'].clear() # obtengo el fitlro de fecha (si esta habilitado): if panel['filtrar_fecha'].value: fecha = panel['fecha'].value.strftime("%Y%m%d") else: fecha = None carpeta = panel['carpeta'].text or "." for fn in os.listdir(carpeta): if fnmatch.fnmatch(fn, 'TB_???????????_*.txt'): # filtro por fecha (si esta tildado): # TB_20111111112_000000_20080124_000001.txt fecha_fn = fn[22:30] if fecha and fecha != fecha_fn: continue txt = fn xml = os.path.splitext(fn)[0] + ".xml" if not os.path.exists(os.path.join(carpeta, xml)): xml = "" lv.items[fn] = {'txt': txt, 'xml': xml} def procesar_archivos(evt): # establezco la barra de progreso con la cantidad de archivos: panel['gauge'].max = len(panel['archivos'].items) # recorro los archivos a procesar: for i, item in enumerate(panel['archivos'].items): panel['gauge'].value = i + 1 procesar_archivo(item, enviar=True) def cargar_archivo(evt): # obtengo y proceso el archivo seleccionado: item = evt.target.get_selected_items()[0] procesar_archivo(item) def abrir_archivo(evt): # obtengo y proceso el archivo seleccionado: item = evt.target.get_selected_items()[0] fn = os.path.join(panel['carpeta'].text, item['txt']) try: os.startfile(fn) except AttributeError: import subprocess subprocess.run(["gedit", fn], check=False) def procesar_archivo(item, enviar=False): "Enviar archivo a ARBA y analizar la respuesta" # establezco credenciales: cuit = item['txt'][3:14] cot.Usuario = panel['usuario'].value = cuit cot.Password = panel['clave'].value = getpass(cuit) cot.Conectar(panel['url'].text, trace=True) # obtengo la ruta al archivo de texto y xml carpeta = panel['carpeta'].text fn = os.path.join(carpeta, item['txt']) xml = item['xml'] if xml: xml = os.path.join(carpeta, xml) elif not enviar: return # llamada al webservice: cot.PresentarRemito(fn, testing=xml) # grabo el xml devuelto: if not xml: xml = os.path.splitext(fn)[0] + ".xml" with open(xml, "w") as f: f.write(cot.XmlResponse) if cot.Excepcion and enviar: gui.alert(cot.Traceback, cot.Excepcion) if cot.TipoError and enviar: gui.alert(cot.MensajeError, "Error %s: %s" % (cot.TipoError, cot.CodigoError)) # actualizo los datos devueltos en el listado item['cuit'] = cot.CuitEmpresa item['nro'] = cot.NumeroComprobante item['md5'] = cot.CodigoIntegridad #assert item['txt'] == cot.NombreArchivo # limpio, enumero y agrego los remitos para el archivo seleccionado: remitos = panel['remitos'] item['remitos'] = [] panel['errores'].items = [] remitos.items = [] i = 0 while cot.LeerValidacionRemito(): print "REMITO", i errores = [] remito = {'nro': cot.NumeroUnico, 'proc': cot.Procesado, 'errores': errores} remitos.items[i] = remito item['remitos'].append(remito) i += 1 while cot.LeerErrorValidacion(): print "Error Validacion:", "|", cot.CodigoError, "|", cot.MensajeError errores.append({'codigo': cot.CodigoError, 'descripcion': cot.MensajeError}) def cargar_errores(evt): # obtengo el remito seleccionado: item = evt.target.get_selected_items()[0] # limpio, enumero y agrego los errores para el remito seleccionado: errores = panel['errores'] errores.items = [] for i, error in enumerate(item['errores']): print i, error errores.items[i] = error def filtro_fecha(evt): panel['fecha'].enabled = evt.target.value listar_archivos() def mover_archivos(evt=None): carpeta = panel['carpeta'].text if carpeta != "datos": gui.alert("No se puede mover archivos de carpeta %s" % carpeta) i = 0 print panel['archivos'].items for item in panel['archivos'].items: procesado = all([remito.get('proc', 'NO') == 'SI' for remito in item.get('remitos', [])]) if procesado and item.get('remitos'): for fn in (item['txt'], item['xml']): fn0 = os.path.join("datos", fn) fn1 = os.path.join("procesados", fn) try: os.rename(fn0, fn1) i += 1 except Exception, e: gui.alert(unicode(e), "No se puede mover %s" % fn) gui.alert("Se movieron: %s archivos" % i) listar_archivos() panel['archivos'].onitemselected = cargar_archivo panel['archivos'].onmousedclick = abrir_archivo panel['remitos'].onitemselected = cargar_errores panel['filtrar_fecha'].onclick = filtro_fecha panel['fecha'].onchange = listar_archivos panel['carpeta'].onchange = listar_archivos panel['mover'].onclick = mover_archivos panel['procesar'].onclick = procesar_archivos panel['clave'].onchange = grabar_clave if __name__ == "__main__": mywin.show() mywin.title = u"%s - %s" % (mywin.title, cot.Version.decode("latin1")) mywin['statusbar'].text = "" listar_archivos() gui.main_loop() passwd_db.close()