From caa360865ba0a934969e2644e4ecc39aada70690 Mon Sep 17 00:00:00 2001 From: Mariano Reingart Date: Sat, 26 Jun 2021 18:59:36 -0300 Subject: [PATCH 1/7] RECE1: agrego campo fecha_hs_gen --- rece1.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rece1.py b/rece1.py index 2a6c1e7d3..7734f0282 100644 --- a/rece1.py +++ b/rece1.py @@ -15,7 +15,7 @@ __author__ = "Mariano Reingart (reingart@gmail.com)" __copyright__ = "Copyright (C) 2010-2015 Mariano Reingart" __license__ = "GPL 3.0" -__version__ = "1.38c" +__version__ = "1.38d" import datetime import os @@ -79,6 +79,7 @@ ('fecha_serv_desde', 8, A), # opcional solo conceptos 2 y 3 ('fecha_serv_hasta', 8, A), # opcional solo conceptos 2 y 3 ('tipo_cbte', 3, N), ('punto_vta', 5, N), + ('fecha_hs_gen', 14, A), # CAEA: yyyymmddhhmiss generaci髇 p/ contingencia ] #DETALLE = [ From 03bc8977fb3a7f63bc7bbd8cddc21c0f939d2468 Mon Sep 17 00:00:00 2001 From: Mariano Reingart Date: Sat, 26 Jun 2021 19:03:50 -0300 Subject: [PATCH 2/7] WSRemAzucar: agrego campo es_entrega_mostrador --- wsremazucar.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wsremazucar.py b/wsremazucar.py index 36a9843d6..af02064f3 100644 --- a/wsremazucar.py +++ b/wsremazucar.py @@ -17,7 +17,7 @@ __author__ = "Mariano Reingart " __copyright__ = "Copyright (C) 2018-2019 Mariano Reingart" __license__ = "LGPL 3.0" -__version__ = "1.03d" +__version__ = "1.04a" LICENCIA = """ wsremhairna.py: Interfaz para generar Remito Electr贸nico Az煤car AFIP v2.0.3 @@ -152,7 +152,7 @@ def CrearRemito(self, tipo_comprobante, punto_emision, tipo_titular_mercaderia, cuit_titular_mercaderia=None, cuit_autorizado_retirar=None, cuit_productor_contrato=None, numero_maquila=None, - cod_remito=None, estado=None, + cod_remito=None, estado=None, es_entrega_mostrador=None, **kwargs): "Inicializa internamente los datos de un remito para autorizar" self.remito = {'puntoEmision': punto_emision, 'tipoTitularMercaderia': tipo_titular_mercaderia, @@ -161,6 +161,7 @@ def CrearRemito(self, tipo_comprobante, punto_emision, 'cuitProductorContrato': cuit_productor_contrato, 'numeroMaquila': numero_maquila, 'codRemito': cod_remito, + 'esEntregaMostrador': es_entrega_mostrador, 'arrayMercaderias': [], 'arrayContingencias': [], } return True From 268c0a0072dc7724582161adc6c9a68c1d972f1a Mon Sep 17 00:00:00 2001 From: Mariano Reingart Date: Sat, 31 Jul 2021 21:10:01 -0300 Subject: [PATCH 3/7] WSRemAzucar: agrego InformarContingencia Metodos a utilizar (pseudocodigo): * CrearRemito(cod_remito=...) * AgregarContingencia(tipo=1, observacion="") * AgregarMercaderia(orden=1, cant_unidad=1) * InformarContingencia() Devuelve resultado: "A" (aprobado), "R" (rechazado), "O" (observado) Ej: python wsremazucar.py --informar-contingencia --prueba --cargar --- wsremazucar.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/wsremazucar.py b/wsremazucar.py index af02064f3..1ddbf776f 100644 --- a/wsremazucar.py +++ b/wsremazucar.py @@ -17,7 +17,7 @@ __author__ = "Mariano Reingart " __copyright__ = "Copyright (C) 2018-2019 Mariano Reingart" __license__ = "LGPL 3.0" -__version__ = "1.04a" +__version__ = "1.05a" LICENCIA = """ wsremhairna.py: Interfaz para generar Remito Electr贸nico Az煤car AFIP v2.0.3 @@ -343,6 +343,30 @@ def AnularRemito(self): self.AnalizarRemito(ret) return bool(self.CodRemito) + @inicializar_y_capturar_excepciones + def InformarContingencia(self, archivo="qr.png"): + "Reportar una contingencia que impide el env铆o de la mercader铆a y realiza la anulaci贸n del remito" + mercaderias = [] + for it in self.remito['arrayMercaderias']: + mercaderia = it['mercaderia'] + mercaderias.append({"mercaderia": [mercaderia]}) + + response = self.client.informarContingencia( + authRequest={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit}, + informarContingencia={ + 'codigoRemito': self.remito["codRemito"], + 'tipoContingencia': self.remito['arrayContingencias'][0]["contingencia"]["tipoContingencia"], + 'observaciones': self.remito['arrayContingencias'][0]["contingencia"]["observacion"], + 'arrayMercaderiaPerdida': mercaderias, + }) + ret = response.get("informarContingenciaReturn") + if ret: + self.__analizar_errores(ret) + self.__analizar_observaciones(ret) + self.__analizar_evento(ret) + self.AnalizarRemito(ret, archivo) + return ret["resultado"] + @inicializar_y_capturar_excepciones def ConsultarUltimoRemitoEmitido(self, tipo_comprobante=995, punto_emision=1): "Obtener el 煤ltimo n煤mero de remito que se emiti贸 por tipo de comprobante y punto de emisi贸n" @@ -619,8 +643,10 @@ def ConsultarCodigosDomicilio(self, cuit_titular=1, sep="||"): cuit_autorizado_retirar='20111111112', cuit_productor_contrato=None, numero_maquila=9999, - cod_remito=None, estado=None, + cod_remito=1234 if '--informar-contingencia' in sys.argv else None, + estado=None, id_req=int(time.time()), + es_entrega_mostrador='S', ) if "--autorizar" in sys.argv: rec["estado"] = 'A' # 'A': Autorizar, 'D': Denegar @@ -675,6 +701,9 @@ def ConsultarCodigosDomicilio(self, cuit_titular=1, sep="||"): if '--anular' in sys.argv: ok = wsremazucar.AnularRemito() + if '--informar-contingencia' in sys.argv: + ok = wsremazucar.InformarContingencia() + if ok is not None: print "Resultado: ", wsremazucar.Resultado print "Cod Remito: ", wsremazucar.CodRemito From d02eb5a293aa77c6cc2e39fc7838b54ec6a8fead Mon Sep 17 00:00:00 2001 From: Mariano Reingart Date: Sat, 31 Jul 2021 21:42:34 -0300 Subject: [PATCH 4/7] WSFEv1: ajuste TLB --- typelib/wsaa.tlb | Bin 4704 -> 4704 bytes typelib/wsfev1.idl | 24 +++++++++++++++++++----- typelib/wsfev1.tlb | Bin 8988 -> 9412 bytes wsfev1.py | 2 +- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/typelib/wsaa.tlb b/typelib/wsaa.tlb index a0d6330296b3fe579e52b80a5fbb47ae2530aa9e..00d20b30cc8a16ae388e719d062470e700437b52 100644 GIT binary patch delta 40 ucmaE$@<3%nFt@ZDYYJq~0iGrb#m9d$Xk%fYhfuR|fFhlL!XW^UkxIeK00Qm+CD*ylh diff --git a/typelib/wsfev1.idl b/typelib/wsfev1.idl index 5ae962f88..44e22747f 100644 --- a/typelib/wsfev1.idl +++ b/typelib/wsfev1.idl @@ -7,7 +7,7 @@ import "unknwn.idl","oaidl.idl"; [ - uuid(9588B307-67B7-4F27-8968-B78A37D342A2), + uuid(FF10876A-3865-48BF-A658-979965C0258A), helpstring("PyAfipWs WSFEv1 interface"), pointer_default(unique), dual, @@ -37,6 +37,7 @@ interface IWSFEv1 : IDispatch [in] BSTR moneda_id, [in] BSTR moneda_ctz, [in] BSTR caea, + [in] BSTR fecha_hs_gen, [out, retval] BOOL * ok); [id( 2)] HRESULT AgregarIva( [in] BSTR iva_id, @@ -56,6 +57,8 @@ interface IWSFEv1 : IDispatch [in] BSTR tipo, [in] BSTR pto_vta, [in] BSTR nro, + [in] BSTR cuit, + [in] BSTR fecha, [out, retval] BOOL * ok); [id( 6)] HRESULT CompUltimoAutorizado( [in] BSTR tipo_cbte, @@ -205,18 +208,29 @@ interface IWSFEv1 : IDispatch [id(74)] HRESULT LeerFacturaX([in] int indice, [out, retval] BOOL * ok); + [id(75)] HRESULT AgregarPeriodoComprobantesAsociados( + [in] BSTR fecha_desde, + [in] BSTR fecha_hasta, + [out, retval] BOOL * ok); + + [id(76)] HRESULT AgregarComprador( + [in] BSTR doc_tipo, + [in] BSTR doc_nro, + [in] BSTR porcentaje, + [out, retval] BOOL * ok); + }; //end interface def [ - uuid(B1D7283C-3EC2-463E-89B4-11F5228E2A15), - version(1.18), - helpstring("PyAfipWs WSFEv1 1.18 Type Library"), + uuid(C7190CBC-FB36-4370-9190-BA46F861F539), + version(1.25), + helpstring("PyAfipWs WSFEv1 1.25 Type Library"), ] library PyAfipWsWSFEv1Lib { importlib("stdole32.tlb"); [ - uuid(D50B5D14-621E-4473-AC63-8A7B5E9DD57F), + uuid(B1DC6AC0-D8F9-4AC2-BEC3-0A568AF03E9B), helpstring("WSFEv1 Component Class") ] coclass WSFEv1 { diff --git a/typelib/wsfev1.tlb b/typelib/wsfev1.tlb index 51ce60986bc8a7db30ea4649ba15c83cfb6f2c80..d2544f1daf8837027891eafcf91e50ee679a042b 100644 GIT binary patch delta 2937 zcmZ`*e@v8R9DiOoetN(GcfiRH!GoDa#-aJM@|Y*T#G*oBmXq`Dgk#9DyTjpzgFkYS zqXm1cuxMion>KAaaigZi%9dNS*`}LwR5oq1rcN?9Tsr%Fo_h~a*0X)S&-eZQdcM!| zzR&yp4wav)>R*^+6&z8D&XQiRuf+_k{3tJE6ygy^3YBR>G+>H6H>3^R&P(frv~G@c zB2DILrP>|&s^(TSUE3sGTDqLn7HgIAk+w8}u^6OL+M|}l9Klm3xJ(&}$}yMV>5S3( z!^(f#Hw^TDRX**yw?>Xc)n<*iOrE@d`P=HRzf0VD;Lb}QM}kOWbcw0uZPO#~>TfDP zYxwYxcf9C;tciAZk1P;kBtEJ4}JY^HQ{}Jpw z3yHl2TY;InQ6zM#FJ?uQ$tW@sc6r^+t{u(69ZlZ0Q)6)}v?AIV#N}Vz9lj8Gju`PE zRaw^8*Lx7EP~M7P9%YV}ixaMB2j#;Aw{}Ci5?5(;@=)S$nn&(k@MDxP$a3RK*=KCj zobs0O)7+_}dsU6!9D zueUVgoZ`f=qiT2i%ifS*<)w%+%-QG~Z&x||ezLfRa1$j2b zhID>USq^G3RcJkOyD8I>gY%0O7Y`#|)z-4`o@(Vgrff?uPA*u&LOTN9ChpcD zzcj7V8s(HJv->(uI#y^?zBZ4~?G1aLM|L*xMX;<14z570H{kPo{2Tnc+XMcch~o{G z1^sTH%i|B$Gq+*HSRisvgwNjN4SKvvPTd00bWMLJu3*TecG?MhlNdgR_--zsA|qOW z4jl2~ShUCQ-VyS(tIbmuC${BL))w&31Wy#7PqzCJq%GuXLGlHnc5m4(UweHpzy9^| zjeG3*_GP8d%Vntp+0`Ab`Sz0h(vr1y``XeqU`p+Y>7roiUybrg>N0ChvJmPLT%3+{@`Plu5_C=F88O~x_NIS z_Pmx6ey*>1j{LDW@Wlr&8iipd$6_%g5^xvsx>OGQ??htO&fz^_K2I6(E=P=bjmUF2 z<+J8>+L-j2*I9WLBQ`f?cp=8+S+gyfA6rCQVvx7Z%bpZHZE3+3dEa77Ip@jokiPf=?QZC+H=rRaV|k1G0; zqEm`ma%s6n(e1gmqPgD-{#i38z@jv})5E#8B>tGg=fk~U%C%W%CGkD1th3tGJe!qO zC@h)PhRKR|B)&<{cT+*;FOMS$b)f0T03d&w!CeW#) zi=NTCH^HX{s08Ye7mM8mpb&`+0&E=^nANut=mFRk+yK}vupBu756}y+xU!vK^=I{V z0BlFtrtnSj4XVnH8C^iPs@kjn)`__vVB^I`h}HTk zz+VO{e-3O|@!58;p<=t>0r>xCzr(u0>d$I_J%K$0-Y2`Z27nC{yEOJS>_^y(u(e<( z##V#P6FM(7@^O;vOZtGDKn)h|1tx(kBvS`;0;9lnz>E{)DTaU%;38nK;FwkbJidd# q7%&+lw=Mo)br;q;2mAw+V9i!w2$%rklaMn|3xt3{;5=YJLHQ4{b;kn$ delta 2483 zcmZuyYfMx}6rNcSc43$2F6<(#i&x{?ZY?hnl`2+zY=Z3?wP=D?%9^r`3ayx6N&1rrKiDR!wMA6Vhm^4QVv=`-Xd6D!s{fX6`v> z&YU@S?)k>T{Tq9Wit_{?o0dt@jp?n_zUnXh@k}A6@nl2e%@txNM(e#jx9?AXUN5xU zXK5#Lm0wm!yV@#Sw9J=b)hzSX&vK!xQ`2&(s4@cAAR^F{)Nu(7hLv z+Tf38F0EO!@z_Z2!-XF{<54GV5wCl9<_-UAhw6t~j=#NU;0Ci4Wq@*~l;xxkAN}Oq z>q}lf)_U&vitk_iQZ=O1cXuNFPWw#COuI7;?ioUir_bod@J@XQ72x=oDi(B@r<#QG z1q9_LQ%G(c^9X#e03rA;GAlGPE13z}fGHpX{U3xGqZMoH*xZeE0W;}-exbc6Q523r zjCC;9!|4h(gC zKCj9)Jf0qs(y5j@Ds7K!YLDY5*`-!yw8$Yfkg-D6sv8-%WKf;W{LVI(qTY2@;~3+= zu0I^>P^X=(xWYcySGLJi^{uN&HmIAfO;}i(wOTf*-C65pT%E{TBKy_lthJsHj+rhJ zb>Rc;FYW7SYmDOfQB{(CNEWNU>_V*mI(w}gRd=%uS)*JzmC&rq*%WR?`k7)&q^-Rr z)^@OY|Esa6UV9ryPZQTqAzt{Eb&XnA1D#9!khOl@hHY*8V=b|c=C^h>Ha4%{4$GL^J@)}i;*EfILzV<*xRiM0LRb}<6%H@HI zvhwPTeDU7E?~UqG-ZI}w*UXji311IRA&Ny@I_ib+C`bNZ_&T@<%H=i|^Cv)|@p0@u zJcc#zGUqd%JKTmGR7c!KH}9zB!z*abXRm!UOaGrZ(BtNb%_3D;d4)umaNtVeQt2G{ zk6AHUDr?>_Gsg$Q6H+TZt8obqdsh2+y)37pCv*Hz>axek;uo;24^q@Wo@Gy~stewb zA$6j_aK(`WeRF_*b#0DD7C!A$K1b6$N7FY)b8(L5e&O@7SCx97j=vQe{@2WkPe{Gv zHIVHoEiZeGFmJ4NzPed+{@s?IKd&`s|Kz+tr1Y>&an2{Cmir7jqIUT{!u`98xm&r4 zD9g3nq2&=R2eiCcvVV@?u3;|@FNx+WF6a*Ro z_Gq#aNrWUoav`fF02Yr$V?n0?k_mf%Q#vS-O<&U@MmBqLF*%eCz8I(iNM{WgqX7Av ze3}4Aqx?%rAjR+@age>7_#R}P8lV9nZIX{kA|ws=K@x+=040&a$h#za(j#e<zXk zp_8%rkTRQq9^f_*#D-CTReJ!GA(8C>D|Z372Lw>12+#wZ25tj6s7@Wgihb;W7zGxk gslSa+LkaA46>vJy*MLr75SRe$=)oZ%0(1cX0zFzp6aWAK diff --git a/wsfev1.py b/wsfev1.py index 91f23a9ec..b990e399d 100644 --- a/wsfev1.py +++ b/wsfev1.py @@ -80,7 +80,7 @@ class WSFEv1(BaseWS): _reg_clsid_ = "{CA0E604D-E3D7-493A-8880-F6CDD604185E}" if TYPELIB: - _typelib_guid_ = '{B1D7283C-3EC2-463E-89B4-11F5228E2A15}' + _typelib_guid_ = '{C7190CBC-FB36-4370-9190-BA46F861F539}' _typelib_version_ = 1, 18 _com_interfaces_ = ['IWSFEv1'] ##_reg_class_spec_ = "wsfev1.WSFEv1" From 9014771432f7e26fac6c092daec61813da407640 Mon Sep 17 00:00:00 2001 From: Mariano Reingart Date: Mon, 2 Aug 2021 20:35:51 -0300 Subject: [PATCH 5/7] WSCPE: modulo inicial --- wscpe.py | 797 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 797 insertions(+) create mode 100644 wscpe.py diff --git a/wscpe.py b/wscpe.py new file mode 100644 index 000000000..a5def31bd --- /dev/null +++ b/wscpe.py @@ -0,0 +1,797 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation; either version 3, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +# for more details. + +"""M贸dulo para obtener Carta de Porte Electr贸nica +para transporte ferroviario y automotor RG 5017/2021 +""" + +__author__ = "Mariano Reingart " +__copyright__ = "Copyright (C) 2021- Mariano Reingart" +__license__ = "LGPL 3.0" +__version__ = "1.00a" + +LICENCIA = """ +wscpe.py: Interfaz para generar Carta de Porte Electr贸nica AFIP v1.0.0 +Resoluci贸n General 5017/2021 +Copyright (C) 2021 Mariano Reingart reingart@gmail.com +http://www.sistemasagiles.com.ar/trac/wiki/CartadePorte + +Este progarma es software libre, se entrega ABSOLUTAMENTE SIN GARANTIA +y es bienvenido a redistribuirlo bajo la licencia GPLv3. + +Para informaci贸n adicional sobre garant铆a, soporte t茅cnico comercial +e incorporaci贸n/distribuci贸n en programas propietarios ver PyAfipWs: +http://www.sistemasagiles.com.ar/trac/wiki/PyAfipWs +""" + +AYUDA=""" +Opciones: + --ayuda: este mensaje + + --debug: modo depuraci贸n (detalla y confirma las operaciones) + --prueba: genera y autoriza una rec de prueba (no usar en producci贸n!) + --xml: almacena los requerimientos y respuestas XML (depuraci贸n) + --dummy: consulta estado de servidores + + --generar: generar un cpe + --emitir: emite un cpe + --anular: anula un cpe + --autorizar: autoriza un cpe + + --ult: consulta ultimo nro cpe emitido + --consultar: consulta un cpe generado + + --tipos_comprobante: tabla de parametros para tipo de comprobante + --tipos_contingencia: tipo de contingencia que puede reportar + --tipos_categoria_emisor: tipos de categor铆as de emisor + --tipos_categoria_receptor: tipos de categor铆as de receptor + --tipos_estados: estados posibles en los que puede estar un cpe granosero + --grupos_granos' grupos de los distintos tipos de cortes de granos + --tipos_granos': tipos de corte de granos + --codigos_domicilio: codigos de depositos habilitados para el cuit + +Ver wscpe.ini para par谩metros de configuraci贸n (URL, certificados, etc.)" +""" + +import os, sys, time, base64 +from utils import date +import traceback +from pysimplesoap.client import SoapFault +import utils + +# importo funciones compartidas: +from utils import json, BaseWS, inicializar_y_capturar_excepciones, get_install_dir, json_serializer + + +# constantes de configuraci贸n (producci贸n/homologaci贸n): + +WSDL = ["https://serviciosjava.afip.gob.ar/cpe-ws/services/wscpe?wsdl", + "https://fwshomo.afip.gov.ar/wscpe/services/soap?wsdl"] + +DEBUG = False +XML = False +CONFIG_FILE = "wscpe.ini" +HOMO = True +ENCABEZADO = [] + + +class WSCPE(BaseWS): + "Interfaz para el WebService de Carta de Porte Electr贸nica (Version 1)" + _public_methods_ = ['Conectar', 'Dummy', 'SetTicketAcceso', 'DebugLog', + 'GenerarCPE', 'EmitirCPE', 'AutorizarCPE', 'AnularCPE', 'ConsultarCPE', + 'InformarContingencia', 'ModificarViaje', 'RegistrarRecepcion', 'ConsultarUltimoCPEEmitido', + 'CrearCPE', 'AgregarViaje', 'AgregarVehiculo', 'AgregarMercaderia', 'AgregarReceptor', + 'AgregarDatosAutorizacion', 'AgregarContingencia', + 'ConsultarTiposMercaderia', 'ConsultarTiposEmbalaje', 'ConsultarTiposUnidades', 'ConsultarTiposComprobante', + 'ConsultarTiposComprobante', 'ConsultarTiposContingencia', 'ConsultarCodigosDomicilio', 'ConsultarPaises', + 'SetParametros', 'SetParametro', 'GetParametro', 'AnalizarXml', 'ObtenerTagXml', 'LoadTestXML', + ] + _public_attrs_ = ['XmlRequest', 'XmlResponse', 'Version', 'Traceback', 'Excepcion', 'LanzarExcepciones', + 'Token', 'Sign', 'Cuit', 'AppServerStatus', 'DbServerStatus', 'AuthServerStatus', + 'CodCPE', 'TipoComprobante', 'PuntoEmision', + 'NroCPE', 'CodAutorizacion', 'FechaVencimiento', 'FechaEmision', 'Estado', 'Resultado', 'QR', + 'ErrCode', 'ErrMsg', 'Errores', 'ErroresFormato', 'Observaciones', 'Obs', 'Evento', 'Eventos', + ] + _reg_progid_ = "WSCPE" + _reg_clsid_ = "{37F6A7B5-344E-45C5-9198-0CF7B206F409}" + + # Variables globales para BaseWS: + HOMO = HOMO + WSDL = WSDL[HOMO] + LanzarExcepciones = False + Version = "%s %s" % (__version__, HOMO and 'Homologaci贸n' or '') + + def Conectar(self, *args, **kwargs): + ret = BaseWS.Conectar(self, *args, **kwargs) + return ret + + def inicializar(self): + self.AppServerStatus = self.DbServerStatus = self.AuthServerStatus = None + self.CodCPE = self.TipoComprobante = self.PuntoEmision = None + self.NroCPE = self.CodAutorizacion = self.FechaVencimiento = self.FechaEmision = None + self.Estado = self.Resultado = self.QR = None + self.Errores = [] + self.ErroresFormato = [] + self.Observaciones = [] + self.Eventos = [] + self.Evento = self.ErrCode = self.ErrMsg = self.Obs = "" + + def __analizar_errores(self, ret): + "Comprueba y extrae errores si existen en la respuesta XML" + self.Errores = [err['codigoDescripcion'] for err in ret.get('arrayErrores', [])] + self.ErroresFormato = [err['codigoDescripcionString'] for err in ret.get('arrayErroresFormato', [])] + errores = self.Errores + self.ErroresFormato + self.ErrCode = ' '.join(["%(codigo)s" % err for err in errores]) + self.ErrMsg = '\n'.join(["%(codigo)s: %(descripcion)s" % err for err in errores]) + + def __analizar_observaciones(self, ret): + "Comprueba y extrae observaciones si existen en la respuesta XML" + self.Observaciones = [obs["codigoDescripcion"] for obs in ret.get('arrayObservaciones', [])] + self.Obs = '\n'.join(["%(codigo)s: %(descripcion)s" % obs for obs in self.Observaciones]) + + def __analizar_evento(self, ret): + "Comprueba y extrae el wvento informativo si existen en la respuesta XML" + evt = ret.get('evento') + if evt: + self.Eventos = [evt] + self.Evento = "%(codigo)s: %(descripcion)s" % evt + + @inicializar_y_capturar_excepciones + def CrearCPE(self, tipo_cp, sucursal, + tipo_titular_mercaderia, + cuit_solicitante=None, cuit_autorizado_retirar=None, + cuit_productor_contrato=None, numero_maquila=None, + cod_cpe=None, estado=None, es_entrega_mostrador=None, + **kwargs): + "Inicializa internamente los datos de un cpe para autorizar" + self.cpe = {'puntoEmision': punto_emision, 'tipoTitularMercaderia': tipo_titular_mercaderia, + 'cuitTitularMercaderia': cuit_titular_mercaderia, + 'cuitAutorizadoRetirar': cuit_autorizado_retirar, + 'cuitProductorContrato': cuit_productor_contrato, + 'numeroMaquila': numero_maquila, + 'codCPE': cod_cpe, + 'esEntregaMostrador': es_entrega_mostrador, + 'arrayMercaderias': [], 'arrayContingencias': [], + } + return True + + @inicializar_y_capturar_excepciones + def AgregarReceptor(self, cuit_pais_receptor, + cuit_receptor=None, cod_dom_receptor=None, + cuit_despachante=None, codigo_aduana=None, + denominacion_receptor=None, domicilio_receptor=None, **kwargs): + "Agrega la informaci贸n referente al viaje del cpe electr贸nico granosero" + receptor = {'cuitPaisReceptor': cuit_pais_receptor} + if cuit_receptor: + receptor['receptorNacional'] = {'codDomReceptor': cod_dom_receptor, + 'cuitReceptor':cuit_receptor} + else: + receptor['receptorExtranjero'] = { + 'codigoAduana': codigo_aduana, + 'cuitDespachante': cuit_despachante, + 'denominacionReceptor': denominacion_receptor, + 'domicilioReceptor': domicilio_receptor} + self.cpe['receptor'] = receptor + + @inicializar_y_capturar_excepciones + def AgregarViaje(self, fecha_inicio_viaje, distancia_km, cod_pais_transportista, ducto=None, **kwargs): + "Agrega la informaci贸n referente al viaje del cpe electr贸nico granosero" + self.cpe.update({ + 'viaje': { + 'fechaInicioViaje': fecha_inicio_viaje , + 'kmDistancia': distancia_km, + 'tramo': [{ + }] + }}) + + if ducto: + transporte = self.cpe['viaje']['tramo'][0]['ducto'] = ducto + else: + self.cpe['viaje']['tramo'][0]['automotor'] = { + 'codPaisTransportista': cod_pais_transportista, + } + return True + + @inicializar_y_capturar_excepciones + def AgregarVehiculo(self, dominio_vehiculo, dominio_acoplado=None, + cuit_transportista=None, cuit_conductor=None, + apellido_conductor=None, cedula_conductor=None, denom_transportista=None, + id_impositivo=None, nombre_conductor=None, + **kwargs): + "Agrega la informaci贸n referente al vehiculo usado en el viaje del cpe electr贸nico granosero" + transporte = self.cpe['viaje']['tramo'][0]['automotor'] + vehiculo = { + 'dominioVehiculo': dominio_vehiculo, + 'dominioAcoplado': dominio_acoplado, + } + transporte.update(vehiculo) + + if cuit_transportista: + transporte['transporteNacional'] = { + 'cuitTransportista': cuit_transportista, + 'cuitConductor': cuit_conductor, + } + else: + transporte['transporteExtranjero'] = { + 'apellidoConductor': apellido_conductor, + 'cedulaConductor': cedula_conductor, + 'denomTransportista': denom_transportista, + 'idImpositivo': id_impositivo, + 'nombreConductor': nombre_conductor, + } + + return True + + @inicializar_y_capturar_excepciones + def AgregarMercaderia(self, orden, cod_tipo_prod, cod_tipo_emb, cantidad_emb, cod_tipo_unidad, cant_unidad, + anio_safra, **kwargs): + "Agrega la informaci贸n referente a la mercader铆a del cpe electr贸nico granosero" + mercaderia = dict(orden=orden, + tipoProducto=cod_tipo_prod, + tipoEmbalaje=cod_tipo_emb, + unidadMedida=cod_tipo_unidad, + cantidad=cant_unidad, + anioZafra=anio_safra, + ) + self.cpe['arrayMercaderias'].append(dict(mercaderia=mercaderia)) + return True + + @inicializar_y_capturar_excepciones + def AgregarDatosAutorizacion(self, nro_cpe=None, cod_autorizacion=None, fecha_emision=None, fecha_vencimiento=None, **kwargs): + "Agrega la informaci贸n referente a los datos de autorizaci贸n del cpe electr贸nico granosero" + self.cpe['datosEmision'] = dict(nroCPE=nro_cpe, codAutorizacion=cod_autorizacion, + fechaEmision=fecha_emision, fechaVencimiento=fecha_vencimiento, + ) + return True + + @inicializar_y_capturar_excepciones + def AgregarContingencias(self, tipo=None, observacion=None, **kwargs): + "Agrega la informaci贸n referente a los opcionales de la liq. seq." + contingencia = dict(tipoContingencia=tipo, observacion=observacion) + self.cpe['arrayContingencias'].append(dict(contingencia=contingencia)) + return True + + @inicializar_y_capturar_excepciones + def GenerarCPE(self, id_req, archivo="qr.png"): + "Informar los datos necesarios para la generaci贸n de un cpe nuevo" + if not self.cpe['arrayContingencias']: + del self.cpe['arrayContingencias'] + response = self.client.generarCPE( + authRequest={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit}, + idReqCliente=id_req, cpe=self.cpe) + ret = response.get("generarCPEReturn") + if ret: + self.__analizar_errores(ret) + self.__analizar_observaciones(ret) + self.__analizar_evento(ret) + self.AnalizarCPE(ret, archivo) + return bool(self.CodCPE) + + def AnalizarCPE(self, ret, archivo=None): + "Extrae el resultado del cpe, si existen en la respuesta XML" + if ret: + datos_aut = ret.get('cpeDatosAutorizacion') + if datos_aut: + self.CodCPE = datos_aut.get("codigoCPE") + self.TipoComprobante = datos_aut.get("idTipoComprobante") + self.NroCPE = datos_aut.get('nroComprobante') + self.CodAutorizacion = datos_aut.get('codigoAutorizacion') + self.FechaEmision = datos_aut.get('fechaEmision') + self.FechaVencimiento = datos_aut.get('fechaVencimiento') + self.Estado = ret.get('estado') + self.Resultado = ret.get('resultado') + self.QR = ret.get('qr') or "" + if archivo: + f = open(archivo, "wb") + f.write(self.QR) + f.close() + + @inicializar_y_capturar_excepciones + def EmitirCPE(self, archivo="qr.png"): + "Emitir CPEs que se encuentren en estado Pendiente de Emitir." + response = self.client.emitirCPE( + authRequest={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit}, + emitirCPE=dict( + codigoCPE=self.cpe['codCPE'], + ) + ) + ret = response.get("emitirCPEReturn") + if ret: + self.__analizar_errores(ret) + self.__analizar_observaciones(ret) + self.__analizar_evento(ret) + self.AnalizarCPE(ret, archivo) + return bool(self.CodCPE) + + @inicializar_y_capturar_excepciones + def AutorizarCPE(self, archivo="qr.png"): + "Autorizar o denegar un cpe (cuando corresponde autorizacion) por parte del titular/depositario" + response = self.client.autorizarCPE( + authRequest={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit}, + codCPE=self.cpe['codCPE'], + estado=self.cpe['estado']) + ret = response.get("autorizarCPEReturn") + if ret: + self.__analizar_errores(ret) + self.__analizar_observaciones(ret) + self.__analizar_evento(ret) + self.AnalizarCPE(ret, archivo) + return bool(self.CodCPE) + + @inicializar_y_capturar_excepciones + def AnularCPE(self): + "Anular un cpe generado que a煤n no haya sido emitido" + response = self.client.anularCPE( + authRequest={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit}, + codCPE=self.cpe['codCPE']) + ret = response.get("anularCPEReturn") + if ret: + self.__analizar_errores(ret) + self.__analizar_observaciones(ret) + self.__analizar_evento(ret) + self.AnalizarCPE(ret) + return bool(self.CodCPE) + + @inicializar_y_capturar_excepciones + def InformarContingencia(self, archivo="qr.png"): + "Reportar una contingencia que impide el env铆o de la mercader铆a y realiza la anulaci贸n del cpe" + mercaderias = [] + for it in self.cpe['arrayMercaderias']: + mercaderia = it['mercaderia'] + mercaderias.append({"mercaderia": [mercaderia]}) + + response = self.client.informarContingencia( + authRequest={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit}, + informarContingencia={ + 'codigoCPE': self.cpe["codCPE"], + 'tipoContingencia': self.cpe['arrayContingencias'][0]["contingencia"]["tipoContingencia"], + 'observaciones': self.cpe['arrayContingencias'][0]["contingencia"]["observacion"], + 'arrayMercaderiaPerdida': mercaderias, + }) + ret = response.get("informarContingenciaReturn") + if ret: + self.__analizar_errores(ret) + self.__analizar_observaciones(ret) + self.__analizar_evento(ret) + self.AnalizarCPE(ret, archivo) + return ret["resultado"] + + @inicializar_y_capturar_excepciones + def ConsultarUltimoCPEEmitido(self, tipo_comprobante=995, punto_emision=1): + "Obtener el 煤ltimo n煤mero de cpe que se emiti贸 por tipo de comprobante y punto de emisi贸n" + response = self.client.consultarUltimoCPEEmitido( + authRequest={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit}, + tipoComprobante=tipo_comprobante, + puntoEmision=punto_emision) + ret = response.get("consultarUltimoCPEReturn", {}) + id_req = ret.get("idReq", 0) + rec = ret.get("cpe", {}) + self.__analizar_errores(ret) + self.__analizar_observaciones(ret) + self.__analizar_evento(ret) + self.AnalizarCPE(rec) + return id_req + + @inicializar_y_capturar_excepciones + def ConsultarCPE(self, cod_cpe=None, id_req=None, + tipo_comprobante=None, punto_emision=None, nro_comprobante=None): + "Obtener los datos de un cpe generado" + ##print(self.client.help("consultarCPE")) + response = self.client.consultarCPE( + authRequest={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit}, + codCPE=cod_cpe, + cuitEmisor=self.Cuit, + idReq=id_req, + tipoComprobante=tipo_comprobante, + puntoEmision=punto_emision, + nroComprobante=nro_comprobante) + ret = response.get("consultarCPEReturn", {}) + id_req = ret.get("idReq", 0) + self.cpe = rec = ret.get("cpe", {}) + self.__analizar_errores(ret) + self.__analizar_observaciones(ret) + self.__analizar_evento(ret) + self.AnalizarCPE(rec) + return id_req + + @inicializar_y_capturar_excepciones + def Dummy(self): + "Obtener el estado de los servidores de la AFIP" + results = self.client.dummy()['dummyReturn'] + self.AppServerStatus = str(results['appserver']) + self.DbServerStatus = str(results['dbserver']) + self.AuthServerStatus = str(results['authserver']) + + @inicializar_y_capturar_excepciones + def ConsultarTiposComprobante(self, sep="||"): + "Obtener el c贸digo y descripci贸n para tipo de comprobante" + ret = self.client.consultarTiposComprobante( + authRequest={ + 'token': self.Token, 'sign': self.Sign, + 'cuitRepresentada': self.Cuit, }, + )['consultarTiposComprobanteReturn'] + self.__analizar_errores(ret) + array = ret.get('arrayTiposComprobante', []) + lista = [it['codigoDescripcion'] for it in array] + return [(u"%s {codigo} %s {descripcion} %s" % (sep, sep, sep)).format(**it) if sep else it for it in lista] + + @inicializar_y_capturar_excepciones + def ConsultarPaises(self, sep="||"): + "Obtener el c贸digo y descripci贸n para los paises" + ret = self.client.consultarPaises( + authRequest={ + 'token': self.Token, 'sign': self.Sign, + 'cuitRepresentada': self.Cuit, }, + )['consultarCodigosPaisReturn'] + self.__analizar_errores(ret) + array = ret.get('arrayPaises', []) + lista = [it['pais'] for it in array] + return [(u"%s {codigo} %s {cuit} %s {nombre} %s {tipoSujeto} %s" % (sep, sep, sep, sep, sep)).format(**it) if sep else it for it in lista] + + @inicializar_y_capturar_excepciones + def ConsultarTiposContingencia(self, sep="||"): + "Obtener el c贸digo y descripci贸n para cada tipo de contingencia que puede reportar" + ret = self.client.consultarTiposContingencia( + authRequest={ + 'token': self.Token, 'sign': self.Sign, + 'cuitRepresentada': self.Cuit, }, + )['codigoDescripcionReturn'] + self.__analizar_errores(ret) + array = ret.get('arrayCodigoDescripcion', []) + lista = [it['codigoDescripcion'] for it in array] + return [(u"%s {codigo} %s {descripcion} %s" % (sep, sep, sep)).format(**it) if sep else it for it in lista] + + @inicializar_y_capturar_excepciones + def ConsultarTiposMercaderia(self, sep="||"): + "Obtener el c贸digo y descripci贸n c贸digos y la descripci贸n para cada tipo de mercader铆a" + ret = self.client.consultarTiposMercaderia( + authRequest={ + 'token': self.Token, 'sign': self.Sign, + 'cuitRepresentada': self.Cuit, }, + )['codigoDescripcionReturn'] + self.__analizar_errores(ret) + array = ret.get('arrayCodigoDescripcion', []) + lista = [it['codigoDescripcion'] for it in array] + return [(u"%s {codigo} %s {descripcion} %s" % (sep, sep, sep)).format(**it) if sep else it for it in lista] + + @inicializar_y_capturar_excepciones + def ConsultarTiposEmbalaje(self, sep="||"): + "Obtener el c贸digo y descripci贸n c贸digos y la descripci贸n para cada tipo de embalaje" + ret = self.client.consultarTiposEmbalaje( + authRequest={ + 'token': self.Token, 'sign': self.Sign, + 'cuitRepresentada': self.Cuit, }, + )['codigoDescripcionReturn'] + self.__analizar_errores(ret) + array = ret.get('arrayCodigoDescripcion', []) + lista = [it['codigoDescripcion'] for it in array] + return [(u"%s {codigo} %s {descripcion} %s" % (sep, sep, sep)).format(**it) if sep else it for it in lista] + + @inicializar_y_capturar_excepciones + def ConsultarTiposUnidades(self, sep="||"): + "Obtener el c贸digo y descripci贸n c贸digos y la descripci贸n para cada tipo de unidades de venta" + ret = self.client.consultarUnidadesMedida( + authRequest={ + 'token': self.Token, 'sign': self.Sign, + 'cuitRepresentada': self.Cuit, }, + )['codigoDescripcionReturn'] + self.__analizar_errores(ret) + array = ret.get('arrayCodigoDescripcion', []) + lista = [it['codigoDescripcion'] for it in array] + return [(u"%s {codigo} %s {descripcion} %s" % (sep, sep, sep)).format(**it) if sep else it for it in lista] + + @inicializar_y_capturar_excepciones + def ConsultarCodigosDomicilio(self, cuit_titular=1, sep="||"): + "Obtener el c贸digo de depositos que tiene habilitados para operar el cuit informado" + ret = self.client.consultarCodigosDomicilio( + authRequest={ + 'token': self.Token, 'sign': self.Sign, + 'cuitRepresentada': self.Cuit, }, + cuitTitularDomicilio=cuit_titular, + )['consultarCodigosDomicilioReturn'] + self.__analizar_errores(ret) + array = ret.get('arrayDomicilios', []) + lista = [it['codigoDescripcion'] for it in array] + return [(u"%s {codigo} %s {descripcion} %s" % (sep, sep, sep)).format(**it) if sep else it for it in lista] + + + +# busco el directorio de instalaci贸n (global para que no cambie si usan otra dll) +if not hasattr(sys, "frozen"): + basepath = __file__ +elif sys.frozen=='dll': + import win32api + basepath = win32api.GetModuleFileName(sys.frozendllhandle) +else: + basepath = sys.executable +INSTALL_DIR = WSCPE.InstallDir = get_install_dir() + + +if __name__ == '__main__': + if '--ayuda' in sys.argv: + print LICENCIA + print AYUDA + sys.exit(0) + + if "--register" in sys.argv or "--unregister" in sys.argv: + import win32com.server.register + win32com.server.register.UseCommandLine(WSCPE) + sys.exit(0) + + from ConfigParser import SafeConfigParser + + try: + + if "--version" in sys.argv: + print "Versi贸n: ", __version__ + + for arg in sys.argv[1:]: + if arg.startswith("--"): + break + print "Usando configuraci贸n:", arg + CONFIG_FILE = arg + + config = SafeConfigParser() + config.read(CONFIG_FILE) + CERT = config.get('WSAA','CERT') + PRIVATEKEY = config.get('WSAA','PRIVATEKEY') + CUIT = config.get('WSCPE','CUIT') + ENTRADA = config.get('WSCPE','ENTRADA') + SALIDA = config.get('WSCPE','SALIDA') + + if config.has_option('WSAA','URL') and not HOMO: + wsaa_url = config.get('WSAA','URL') + else: + wsaa_url = None + if config.has_option('WSCPE','URL') and not HOMO: + wscpe_url = config.get('WSCPE','URL') + else: + wscpe_url = WSDL[HOMO] + + if config.has_section('DBF'): + conf_dbf = dict(config.items('DBF')) + if DEBUG: print "conf_dbf", conf_dbf + else: + conf_dbf = {} + + DEBUG = '--debug' in sys.argv + XML = '--xml' in sys.argv + + if DEBUG: + print "Usando Configuraci贸n:" + print "wsaa_url:", wsaa_url + print "wscpe_url:", wscpe_url + + # obteniendo el TA + from wsaa import WSAA + wsaa = WSAA() + ta = wsaa.Autenticar("wscpe", CERT, PRIVATEKEY, wsaa_url, debug=DEBUG) + ##if not ta: + ## sys.exit("Imposible autenticar con WSAA: %s" % wsaa.Excepcion) + + # cliente soap del web service + wscpe = WSCPE() + wscpe.Conectar(wsdl=wscpe_url) + print(wscpe.client.help("autorizarCPEAutomotor")) + wscpe.SetTicketAcceso(ta) + wscpe.Cuit = CUIT + ok = None + + if '--dummy' in sys.argv: + ret = wscpe.Dummy() + print "AppServerStatus", wscpe.AppServerStatus + print "DbServerStatus", wscpe.DbServerStatus + print "AuthServerStatus", wscpe.AuthServerStatus + sys.exit(0) + + if '--ult' in sys.argv: + try: + pto_emision = int(sys.argv[sys.argv.index("--ult") + 1]) + except IndexError, ValueError: + pto_emision = 1 + try: + tipo_cbte = int(sys.argv[sys.argv.index("--ult") + 1]) + except IndexError, ValueError: + tipo_comprobante = 995 + rec = {} + print "Consultando ultimo cpe pto_emision=%s tipo_comprobante=%s" % (pto_emision, tipo_comprobante) + ok = wscpe.ConsultarUltimoCPEEmitido(tipo_comprobante, pto_emision) + if wscpe.Excepcion: + print >> sys.stderr, "EXCEPCION:", wscpe.Excepcion + if DEBUG: print >> sys.stderr, wscpe.Traceback + print "Ultimo Nro de CPE", wscpe.NroCPE + print "Errores:", wscpe.Errores + + if '--consultar' in sys.argv: + rec = {} + try: + cod_cpe = sys.argv[sys.argv.index("--consultar") + 1] + print "Consultando cpe cod_cpe=%s" % (cod_cpe, ) + ok = wscpe.ConsultarCPE(cod_cpe=cod_cpe) + except IndexError, ValueError: + pto_emision = raw_input("Punto de emision [1]:") or 1 + tipo_cbte = raw_input("Tipo de comprobante [995]:") or 995 + nro_comprobante = raw_input("Nro de comprobante:") or 1 + ok = wscpe.ConsultarCPE(tipo_comprobante=tipo_cbte, + punto_emision=pto_emision, + nro_comprobante=nro_comprobante) + if wscpe.Excepcion: + print >> sys.stderr, "EXCEPCION:", wscpe.Excepcion + if DEBUG: print >> sys.stderr, wscpe.Traceback + print "Ultimo Nro de CPE", wscpe.NroCPE + print "Errores:", wscpe.Errores + if DEBUG: + import pprint + pprint.pprint(wscpe.cpe) + + ##wscpe.client.help("generarCPE") + if '--prueba' in sys.argv: + rec = dict( + tipo_comprobante=997, punto_emision=1, + tipo_titular_mercaderia=1, + cuit_titular_mercaderia='20222222223', + cuit_autorizado_retirar='20111111112', + cuit_productor_contrato=None, + numero_maquila=9999, + cod_cpe=1234 if '--informar-contingencia' in sys.argv else None, + estado=None, + id_req=int(time.time()), + es_entrega_mostrador='S', + ) + if "--autorizar" in sys.argv: + rec["estado"] = 'A' # 'A': Autorizar, 'D': Denegar + rec['receptor'] = dict( + cuit_pais_receptor='50000000016', + cuit_receptor='20111111112', cod_dom_receptor=1, + cuit_despachante=None, codigo_aduana=None, + denominacion_receptor=None, domicilio_receptor=None) + rec['viaje'] = dict(fecha_inicio_viaje='2020-04-01', distancia_km=999, cod_pais_transportista=200, ducto="S") + rec['viaje']['vehiculo'] = dict( + dominio_vehiculo='AAA000', dominio_acoplado='ZZZ000', + cuit_transportista='20333333334', cuit_conductor='20333333334', + apellido_conductor=None, cedula_conductor=None, denom_transportista=None, + id_impositivo=None, nombre_conductor=None) + rec['mercaderias'] = [dict(orden=1, cod_tipo_prod=1, cod_tipo_emb=1, cantidad_emb=1, cod_tipo_unidad=1, cant_unidad=1, + anio_safra=2019 )] + rec['datos_autorizacion'] = None # dict(nro_cpe=None, cod_autorizacion=None, fecha_emision=None, fecha_vencimiento=None) + rec['contingencias'] = [dict(tipo=1, observacion="anulacion")] + with open(ENTRADA, "w") as archivo: + json.dump(rec, archivo, sort_keys=True, indent=4) + + if '--cargar' in sys.argv: + with open(ENTRADA, "r") as archivo: + rec = json.load(archivo) + wscpe.CrearCPE(**rec) + if 'receptor' in rec: + wscpe.AgregarReceptor(**rec['receptor']) + if 'viaje' in rec: + wscpe.AgregarViaje(**rec['viaje']) + if not rec["viaje"].get("ducto"): + wscpe.AgregarVehiculo(**rec['viaje']['vehiculo']) + for mercaderia in rec.get('mercaderias', []): + wscpe.AgregarMercaderia(**mercaderia) + datos_aut = rec.get('datos_autorizacion') + if datos_aut: + wscpe.AgregarDatosAutorizacion(**datos_aut) + for contingencia in rec.get('contingencias', []): + wscpe.AgregarContingencias(**contingencia) + + if '--generar' in sys.argv: + if '--testing' in sys.argv: + wscpe.LoadTestXML("tests/xml/wscpe.xml") # cargo respuesta + + ok = wscpe.GenerarCPE(id_req=rec['id_req'], archivo="qr.jpg") + + if '--emitir' in sys.argv: + ok = wscpe.EmitirCPE() + + if '--autorizar' in sys.argv: + ok = wscpe.AutorizarCPE() + + if '--anular' in sys.argv: + ok = wscpe.AnularCPE() + + if '--informar-contingencia' in sys.argv: + ok = wscpe.InformarContingencia() + + if ok is not None: + print "Resultado: ", wscpe.Resultado + print "Cod CPE: ", wscpe.CodCPE + if wscpe.CodAutorizacion: + print "Numero CPE: ", wscpe.NroCPE + print "Cod Autorizacion: ", wscpe.CodAutorizacion + print "Fecha Emision", wscpe.FechaEmision + print "Fecha Vencimiento", wscpe.FechaVencimiento + print "Estado: ", wscpe.Estado + print "Observaciones: ", wscpe.Observaciones + print "Errores:", wscpe.Errores + print "Errores Formato:", wscpe.ErroresFormato + print "Evento:", wscpe.Evento + rec['cod_cpe'] = wscpe.CodCPE + rec['resultado'] = wscpe.Resultado + rec['observaciones'] = wscpe.Observaciones + rec['fecha_emision'] = wscpe.FechaEmision + rec['fecha_vencimiento'] = wscpe.FechaVencimiento + rec['errores'] = wscpe.Errores + rec['errores_formato'] = wscpe.ErroresFormato + rec['evento'] = wscpe.Evento + + if '--grabar' in sys.argv: + with open(SALIDA, "w") as archivo: + json.dump(rec, archivo, sort_keys=True, indent=4, default=json_serializer) + + # Recuperar par谩metros: + + if '--tipos_comprobante' in sys.argv: + ret = wscpe.ConsultarTiposComprobante() + print "\n".join(ret) + + if '--tipos_contingencia' in sys.argv: + ret = wscpe.ConsultarTiposContingencia() + print "\n".join(ret) + + if '--tipos_mercaderia' in sys.argv: + ret = wscpe.ConsultarTiposMercaderia() + print "\n".join(ret) + + if '--tipos_embalaje' in sys.argv: + ret = wscpe.ConsultarTiposEmbalaje() + print "\n".join(ret) + + if '--tipos_unidades' in sys.argv: + ret = wscpe.ConsultarTiposUnidades() + print "\n".join(ret) + + if '--tipos_categoria_emisor' in sys.argv: + ret = wscpe.ConsultarTiposCategoriaEmisor() + print "\n".join(ret) + + if '--tipos_categoria_receptor' in sys.argv: + ret = wscpe.ConsultarTiposCategoriaReceptor() + print "\n".join(ret) + + if '--tipos_estados' in sys.argv: + ret = wscpe.ConsultarTiposEstado() + print "\n".join(ret) + + if '--paises' in sys.argv: + ret = wscpe.ConsultarPaises() + print "\n".join(ret) + + if '--grupos_granos' in sys.argv: + ret = wscpe.ConsultarGruposAzucar() + print "\n".join(ret) + + if '--tipos_granos' in sys.argv: + for grupo_granos in wscpe.ConsultarGruposAzucar(sep=None): + ret = wscpe.ConsultarTiposAzucar(grupo_granos['codigo']) + print "\n".join(ret) + + if '--codigos_domicilio' in sys.argv: + cuit = raw_input("Cuit Titular Domicilio: ") + ret = wscpe.ConsultarCodigosDomicilio(cuit) + print "\n".join(utils.norm(ret)) + + if wscpe.Errores or wscpe.ErroresFormato: + print "Errores:", wscpe.Errores, wscpe.ErroresFormato + + print "hecho." + + except SoapFault,e: + print "Falla SOAP:", e.faultcode, e.faultstring.encode("ascii","ignore") + sys.exit(3) + except Exception, e: + ex = utils.exception_info() + print ex + if DEBUG: + raise + sys.exit(5) From 94da1ff3ae882141aca5f5497b208d2a829a79dc Mon Sep 17 00:00:00 2001 From: Mariano Reingart Date: Mon, 2 Aug 2021 21:40:02 -0300 Subject: [PATCH 6/7] WSCPE: autorizarCPEAutomotor (req/resp) --- wscpe.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/wscpe.py b/wscpe.py index a5def31bd..06c19e859 100644 --- a/wscpe.py +++ b/wscpe.py @@ -315,11 +315,38 @@ def EmitirCPE(self, archivo="qr.png"): @inicializar_y_capturar_excepciones def AutorizarCPE(self, archivo="qr.png"): "Autorizar o denegar un cpe (cuando corresponde autorizacion) por parte del titular/depositario" - response = self.client.autorizarCPE( - authRequest={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit}, - codCPE=self.cpe['codCPE'], - estado=self.cpe['estado']) - ret = response.get("autorizarCPEReturn") + response = self.client.autorizarCPEAutomotor( + auth={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit}, + solicitud={ + 'cabecera': {'tipoCP': int, 'cuitSolicitante': long, 'sucursal': int, 'nroOrden': int}, + 'origen': {'operador': {'planta': int, 'codProvincia': int, 'codLocalidad': int}, + 'correspondeRetiroProductor': bool, + 'esSolicitanteCampo': unicode, + 'retiroProductor': {'certificadoCOE': long, 'cuitRemitenteComercialProductor': long}, + 'intervinientes': {'cuitMercadoATermino': long, 'cuitCorredorVentaPrimaria': long, 'cuitCorredorVentaSecundaria': long, 'cuitRemitenteComercialVentaSecundaria': long, 'cuitIntermediario': long, 'cuitRemitenteComercialVentaPrimaria': long, 'cuitRepresentanteEntregador': long}, + 'datosCarga': {'pesoTara': int, 'codGrano': int, 'pesoBruto': int, 'cosecha': int}, + 'destino': {'planta': int, 'codProvincia': int, 'esDestinoCampo': unicode, 'codLocalidad': int, 'cuit': long}, + 'destinatario': {'cuit': long}, + 'transporte': {'fechaHoraPartida': datetime.datetime, 'codigoTurno': unicode, 'cuitTransportista': long, 'dominio': [{None: unicode}], 'kmRecorrer': int}, + 'productor': {'codLocalidad': int}}, + } + ) + ret = response.get("respuesta") + # 'cabecera': {'fechaEmision': datetime.datetime, 'sucursal': int, 'planta': int, 'tipoCartaPorte': int, 'nroCPE': long, 'nroOrden': long, 'fechaInicioEstado': datetime.datetime, 'estado': unicode, 'fechaVencimiento': datetime.datetime}, + # 'origen': {'planta': int, 'codProvincia': int, 'domicilio': unicode, 'codLocalidad': int}, + # 'correspondeRetiroProductor': bool, + # 'retiroProductor': { + # 'certificadoCOE': long, + # 'cuitRemitenteComercialProductor': long}, + # 'intervinientes': {'cuitMercadoATermino': long, 'cuitCorredorVentaPrimaria': long, 'cuitCorredorVentaSecundaria': long, 'cuitRemitenteComercialVentaSecundaria': long, 'cuitIntermediario': long, 'cuitRemitenteComercialVentaPrimaria': long, 'cuitRepresentanteEntregador': long}, + # 'datosCarga': { + # 'pesoTara': int, 'codGrano': int, 'pesoBruto': int, 'cosecha': int}, + # 'destino': {'planta': int, 'codProvincia': int, 'codLocalidad': int, 'cuit': long}, + # 'destinatario': {'cuit': long}, + # 'transporte': [{'fechaHoraPartida': datetime.datetime, 'codigoTurno': int, 'cuitTransportista': long, 'dominio': unicode, 'kmRecorrer': int}], + # 'errores': [{'error': [{'descripcion': unicode, 'codigo': unicode}]}], + # 'pdf': b64decode, + # 'metadata': {'servidor': unicode, 'fechaHora': datetime.datetime}} if ret: self.__analizar_errores(ret) self.__analizar_observaciones(ret) From 87aae3022af7b53fa63e10cca1346cbe346c6369 Mon Sep 17 00:00:00 2001 From: Mariano Reingart Date: Wed, 4 Aug 2021 23:48:45 -0300 Subject: [PATCH 7/7] WSCPE: datos de ejemplo para autorizar automotor --- wscpe.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/wscpe.py b/wscpe.py index 06c19e859..5af2849a9 100644 --- a/wscpe.py +++ b/wscpe.py @@ -62,7 +62,7 @@ Ver wscpe.ini para par谩metros de configuraci贸n (URL, certificados, etc.)" """ -import os, sys, time, base64 +import os, sys, time, base64, datetime from utils import date import traceback from pysimplesoap.client import SoapFault @@ -318,17 +318,17 @@ def AutorizarCPE(self, archivo="qr.png"): response = self.client.autorizarCPEAutomotor( auth={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit}, solicitud={ - 'cabecera': {'tipoCP': int, 'cuitSolicitante': long, 'sucursal': int, 'nroOrden': int}, - 'origen': {'operador': {'planta': int, 'codProvincia': int, 'codLocalidad': int}, - 'correspondeRetiroProductor': bool, - 'esSolicitanteCampo': unicode, - 'retiroProductor': {'certificadoCOE': long, 'cuitRemitenteComercialProductor': long}, - 'intervinientes': {'cuitMercadoATermino': long, 'cuitCorredorVentaPrimaria': long, 'cuitCorredorVentaSecundaria': long, 'cuitRemitenteComercialVentaSecundaria': long, 'cuitIntermediario': long, 'cuitRemitenteComercialVentaPrimaria': long, 'cuitRepresentanteEntregador': long}, - 'datosCarga': {'pesoTara': int, 'codGrano': int, 'pesoBruto': int, 'cosecha': int}, - 'destino': {'planta': int, 'codProvincia': int, 'esDestinoCampo': unicode, 'codLocalidad': int, 'cuit': long}, - 'destinatario': {'cuit': long}, - 'transporte': {'fechaHoraPartida': datetime.datetime, 'codigoTurno': unicode, 'cuitTransportista': long, 'dominio': [{None: unicode}], 'kmRecorrer': int}, - 'productor': {'codLocalidad': int}}, + 'cabecera': {'tipoCP': 1, 'cuitSolicitante': 20267565393, 'sucursal': 1, 'nroOrden': 1}, + 'origen': {'operador': {'planta': 1, 'codProvincia': 12, 'codLocalidad': 5544}}, + 'correspondeRetiroProductor': True, + 'esSolicitanteCampo': "N", + 'retiroProductor': {'certificadoCOE': 330100025869, 'cuitRemitenteComercialProductor': 20111111112}, + 'intervinientes': {'cuitMercadoATermino': 20222222223, 'cuitCorredorVentaPrimaria': 20222222223, 'cuitCorredorVentaSecundaria': 20222222223, 'cuitRemitenteComercialVentaSecundaria': 20222222223, 'cuitIntermediario': 20222222223, 'cuitRemitenteComercialVentaPrimaria': 20222222223, 'cuitRepresentanteEntregador': 20222222223}, + 'datosCarga': {'pesoTara': 1000, 'codGrano': 31, 'pesoBruto': 1000, 'cosecha': 910}, + 'destino': {'planta': 1, 'codProvincia': 12, 'esDestinoCampo': "M", 'codLocalidad': 3058, 'cuit': 20111111112}, + 'destinatario': {'cuit': 30000000006}, + 'transporte': {'fechaHoraPartida': datetime.datetime.now(), 'codigoTurno': "00", 'cuitTransportista': 20333333334, 'dominio': "ZZZ000", 'kmRecorrer': 500}, + 'productor': {'codLocalidad': 3059}, } ) ret = response.get("respuesta")