def _get_ws(self, afip_ws): """ Method to be inherited """ ws = super(AfipwsConnection, self)._get_ws(afip_ws) if afip_ws == 'wsfe': from pyafipws.wsfev1 import WSFEv1 ws = WSFEv1() elif afip_ws == "wsfex": from pyafipws.wsfexv1 import WSFEXv1 ws = WSFEXv1() elif afip_ws == "wsmtxca": from pyafipws.wsmtx import WSMTXCA ws = WSMTXCA() elif afip_ws == "wscdc": from pyafipws.wscdc import WSCDC ws = WSCDC() elif afip_ws == "ws_sr_padron_a4": from pyafipws.ws_sr_padron import WSSrPadronA4 ws = WSSrPadronA4() if self.type == 'production': ws.H**O = False ws.WSDL = "https://aws.afip.gov.ar/sr-padron/webservices/personaServiceA4?wsdl" elif afip_ws == "ws_sr_constancia_inscripcion": from pyafipws.ws_sr_padron import WSSrPadronA5 ws = WSSrPadronA5() if self.type == 'production': ws.H**O = False ws.WSDL = "https://aws.afip.gov.ar/sr-padron/webservices/personaServiceA5?wsdl" return ws
def test_pyafipws_dummy(self, cr, uid, ids, context=None): for journal in self.browse(cr, uid, ids): company = journal.company_id tipo_cbte = journal.pyafipws_invoice_type punto_vta = journal.pyafipws_point_of_sale service = journal.pyafipws_electronic_invoice_service # import AFIP webservice helper for electronic invoice if service == "wsfe": from pyafipws.wsfev1 import WSFEv1 ws = WSFEv1() elif service == "wsfex": from pyafipws.wsfexv1 import WSFEXv1 ws = WSFEXv1() elif service == "wsmtxca": from pyafipws.wsmtx import WSMTXCA ws = WSMTXCA() # create the proxy and get the configuration system parameters: cfg = self.pool.get('ir.config_parameter') cache = cfg.get_param(cr, uid, 'pyafipws.cache', context=context) proxy = cfg.get_param(cr, uid, 'pyafipws.proxy', context=context) wsdl = cfg.get_param(cr, uid, 'pyafipws.%s.url' % service, context=context) # connect to the webservice and call to the test method ws.Conectar(cache or "", wsdl or "", proxy or "") ws.Dummy() msg = "AFIP service %s " \ "AppServerStatus: %s DbServerStatus: %s AuthServerStatus: %s" msg = msg % ( service, ws.AppServerStatus, ws.DbServerStatus, ws.AuthServerStatus) self.log(cr, uid, ids[0], msg) return {}
def get_afip_rate(self, service='wsfex'): ''' get rate from afip webservice. ''' pool = Pool() Company = pool.get('company.company') company_id = Transaction().context.get('company') if not company_id: logger.error('The company is not defined') raise UserError( gettext('account_invoice_ar.msg_company_not_defined')) company = Company(company_id) # authenticate against AFIP: ta = company.pyafipws_authenticate(service=service) if service == 'wsfe': ws = WSFEv1() if company.pyafipws_mode_cert == 'homologacion': WSDL = 'https://wswhomo.afip.gov.ar/wsfev1/service.asmx?WSDL' elif company.pyafipws_mode_cert == 'produccion': WSDL = ( 'https://servicios1.afip.gov.ar/wsfev1/service.asmx?WSDL') elif service == 'wsfex': ws = WSFEXv1() if company.pyafipws_mode_cert == 'homologacion': WSDL = 'https://wswhomo.afip.gov.ar/wsfexv1/service.asmx?WSDL' elif company.pyafipws_mode_cert == 'produccion': WSDL = ( 'https://servicios1.afip.gov.ar/wsfexv1/service.asmx?WSDL') else: logger.critical('AFIP ws is not yet supported! %s', service) raise UserError( gettext('account_invoice_ar.msg_webservice_not_supported', service=service)) cache = Company.get_cache_dir() ws.LanzarExcepciones = True try: ws.Conectar(wsdl=WSDL, cache=cache, cacert=True) except Exception as e: msg = ws.Excepcion + ' ' + str(e) logger.error('WSAA connecting to afip: %s' % msg) raise UserError( gettext('account_invoice_ar.msg_wsaa_error', msg=msg)) ws.SetTicketAcceso(ta) ws.Cuit = company.party.vat_number if not self.currency.afip_code: logger.error('AFIP code is empty %s', self.currency.code) raise UserError(gettext('account_invoice_ar.msg_afip_code_empty')) self.rate = Decimal(ws.GetParamCtz('DOL')) self.date = datetime.datetime.strptime(ws.FchCotiz, '%Y%m%d').date()
def get_afip_rate(self, service='wsfex'): ''' get rate from afip webservice. ''' pool = Pool() Company = pool.get('company.company') company_id = Transaction().context.get('company') if not company_id: logger.error('The company is not defined') cls.raise_user_error('company_not_defined') company = Company(company_id) # authenticate against AFIP: auth_data = company.pyafipws_authenticate(service=service) if service == 'wsfe': ws = WSFEv1() if company.pyafipws_mode_cert == 'homologacion': WSDL = 'https://wswhomo.afip.gov.ar/wsfev1/service.asmx?WSDL' elif company.pyafipws_mode_cert == 'produccion': WSDL = ( 'https://servicios1.afip.gov.ar/wsfev1/service.asmx?WSDL') elif service == 'wsfex': ws = WSFEXv1() if company.pyafipws_mode_cert == 'homologacion': WSDL = 'https://wswhomo.afip.gov.ar/wsfexv1/service.asmx?WSDL' elif company.pyafipws_mode_cert == 'produccion': WSDL = ( 'https://servicios1.afip.gov.ar/wsfexv1/service.asmx?WSDL') else: logger.critical('AFIP ws is not yet supported! %s', service) cls.raise_user_error('webservice_not_supported', service) cache_dir = afip_auth.get_cache_dir() ws.LanzarExcepciones = True try: ws.Conectar(wsdl=wsdl, cache=cache_dir) except Exception as e: msg = ws.Excepcion + ' ' + str(e) logger.error('WSAA connecting to afip: %s' % msg) cls.raise_user_error('wsaa_error', msg) ws.Cuit = vat_number ws.Token = auth_data['token'] ws.Sign = auth_data['sign'] if not date: Date = pool.get('ir.date') today = Date.today().strftime("%Y%m%d") if not self.currency.afip_code: logger.error('AFIP code is empty %s', self.currency.code) cls.raise_user_error('afip_code_empty') self.rate = Decimal(ws.GetParamCtz('DOL')) self.date = datetime.datetime.strptime(ws.FchCotiz, '%Y%m%d').date()
def _get_ws(self, afip_ws): """ Method to be inherited """ ws = super(AfipwsConnection, self)._get_ws(afip_ws) if afip_ws == 'wsfe': from pyafipws.wsfev1 import WSFEv1 ws = WSFEv1() elif afip_ws == "wsfex": from pyafipws.wsfexv1 import WSFEXv1 ws = WSFEXv1() elif afip_ws == "wsmtxca": from pyafipws.wsmtx import WSMTXCA ws = WSMTXCA() return ws
def get_wsfexv1(company=None, config=None): "return wsfexv1 object" if not company: company = get_company() company = set_afip_certs(company, config) URL_WSAA = "https://wsaahomo.afip.gov.ar/ws/services/LoginCms?wsdl" URL_WSFEXv1 = "https://wswhomo.afip.gov.ar/wsfexv1/service.asmx?WSDL" crt = get_filename('party_ar/tests/gcoop.crt') key = get_filename('party_ar/tests/gcoop.key') ta = WSAA().Autenticar('wsfex', crt, key, URL_WSAA, cacert=True) wsfexv1 = WSFEXv1() wsfexv1.LanzarExcepciones = True wsfexv1.SetTicketAcceso(ta) wsfexv1.Cuit = company.party.vat_number wsfexv1.Conectar(wsdl=URL_WSFEXv1, cacert=True) return wsfexv1
def get_pyafipws_last_invoice(self, cr, uid, ids, fields_name=None, arg=None, context=None): ret = {} for journal in self.browse(cr, uid, ids): company = journal.company_id tipo_cbte = journal.pyafipws_invoice_type punto_vta = journal.pyafipws_point_of_sale service = journal.pyafipws_electronic_invoice_service # authenticate: auth_data = company.pyafipws_authenticate(service=service) # import AFIP webservice helper for electronic invoice if service == "wsfe": from pyafipws.wsfev1 import WSFEv1 ws = WSFEv1() elif service == "wsfex": from pyafipws.wsfexv1 import WSFEXv1 ws = WSFEXv1() elif service == "wsmtxca": from pyafipws.wsmtx import WSMTXCA ws = WSMTXCA() # create the proxy and get the configuration system parameters: cfg = self.pool.get('ir.config_parameter') cache = cfg.get_param(cr, uid, 'pyafipws.cache', context=context) proxy = cfg.get_param(cr, uid, 'pyafipws.proxy', context=context) wsdl = cfg.get_param(cr, uid, 'pyafipws.%s.url' % service, context=context) # connect to the webservice and call to the query method ws.Conectar(cache or "", wsdl or "", proxy or "") if auth_data['token']: # set AFIP webservice credentials: ws.Cuit = company.pyafipws_cuit ws.Token = auth_data['token'] ws.Sign = auth_data['sign'] # call the webservice method to get the last invoice at AFIP: if service == "wsfe" or service == "wsmtxca": ult = ws.CompUltimoAutorizado(tipo_cbte, punto_vta) elif service == "wsfex": ult = ws.GetLastCMP(tipo_cbte, punto_vta) msg = " - ".join([ws.Excepcion, ws.ErrMsg, ws.Obs]) self.log(cr, uid, ids[0], u"Ult.Cbte: N° %s %s" % (ult, msg)) ret[journal.id] = str(ult) else: msg = auth_data['err_msg'] raise osv.except_osv(_("ERROR"), msg) return ret
def do_pyafipws_request_cae(self): logger = logging.getLogger('pyafipws') "Request to AFIP the invoices' Authorization Electronic Code (CAE)" # if already authorized (electronic invoice with CAE), ignore if self.pyafipws_cae: logger.info(u'Se trata de obtener CAE de la factura que ya tiene. '\ u'Factura: %s, CAE: %s', self.number, self.pyafipws_cae) return # get the electronic invoice type, point of sale and service: pool = Pool() Company = pool.get('company.company') company_id = Transaction().context.get('company') if not company_id: logger.info(u'No hay companía') return company = Company(company_id) tipo_cbte = self.invoice_type.invoice_type punto_vta = self.pos.number service = self.pos.pyafipws_electronic_invoice_service # check if it is an electronic invoice sale point: ##TODO #if not tipo_cbte: # self.raise_user_error('invalid_sequence', pos.invoice_type.invoice_type) # authenticate against AFIP: auth_data = company.pyafipws_authenticate(service=service) # import the AFIP webservice helper for electronic invoice if service == 'wsfe': from pyafipws.wsfev1 import WSFEv1 # local market ws = WSFEv1() if company.pyafipws_mode_cert == 'homologacion': WSDL = "https://wswhomo.afip.gov.ar/wsfev1/service.asmx?WSDL" elif company.pyafipws_mode_cert == 'produccion': WSDL = "https://servicios1.afip.gov.ar/wsfev1/service.asmx?WSDL" #elif service == 'wsmtxca': # from pyafipws.wsmtx import WSMTXCA, SoapFault # local + detail # ws = WSMTXCA() elif service == 'wsfex': from pyafipws.wsfexv1 import WSFEXv1 # foreign trade ws = WSFEXv1() if company.pyafipws_mode_cert == 'homologacion': WSDL = "https://wswhomo.afip.gov.ar/wsfexv1/service.asmx?WSDL" elif company.pyafipws_mode_cert == 'produccion': WSDL = "https://servicios1.afip.gov.ar/wsfexv1/service.asmx?WSDL" else: logger.critical(u'WS no soportado: %s', service) return # connect to the webservice and call to the test method ws.LanzarExcepciones = True ws.Conectar(wsdl=WSDL) # set AFIP webservice credentials: ws.Cuit = company.party.vat_number ws.Token = auth_data['token'] ws.Sign = auth_data['sign'] # get the last 8 digit of the invoice number if self.move: cbte_nro = int(self.move.number[-8:]) else: Sequence = pool.get('ir.sequence') cbte_nro = int( Sequence( self.invoice_type.invoice_sequence.id).get_number_next('')) # get the last invoice number registered in AFIP if service == "wsfe" or service == "wsmtxca": cbte_nro_afip = ws.CompUltimoAutorizado(tipo_cbte, punto_vta) elif service == 'wsfex': cbte_nro_afip = ws.GetLastCMP(tipo_cbte, punto_vta) cbte_nro_next = int(cbte_nro_afip or 0) + 1 # verify that the invoice is the next one to be registered in AFIP if cbte_nro != cbte_nro_next: self.raise_user_error('invalid_invoice_number', (cbte_nro, cbte_nro_next)) # invoice number range (from - to) and date: cbte_nro = cbt_desde = cbt_hasta = cbte_nro_next if self.invoice_date: fecha_cbte = self.invoice_date.strftime("%Y-%m-%d") else: Date = pool.get('ir.date') fecha_cbte = Date.today().strftime("%Y-%m-%d") if service != 'wsmtxca': fecha_cbte = fecha_cbte.replace("-", "") # due and billing dates only for concept "services" concepto = tipo_expo = int(self.pyafipws_concept or 0) if int(concepto) != 1: payments = self.payment_term.compute(self.total_amount, self.currency) last_payment = max(payments, key=lambda x: x[0])[0] fecha_venc_pago = last_payment.strftime("%Y-%m-%d") if service != 'wsmtxca': fecha_venc_pago = fecha_venc_pago.replace("-", "") if self.pyafipws_billing_start_date: fecha_serv_desde = self.pyafipws_billing_start_date.strftime( "%Y-%m-%d") if service != 'wsmtxca': fecha_serv_desde = fecha_serv_desde.replace("-", "") else: fecha_serv_desde = None if self.pyafipws_billing_end_date: fecha_serv_hasta = self.pyafipws_billing_end_date.strftime( "%Y-%m-%d") if service != 'wsmtxca': fecha_serv_hasta = fecha_serv_hasta.replace("-", "") else: fecha_serv_hasta = None else: fecha_venc_pago = fecha_serv_desde = fecha_serv_hasta = None # customer tax number: if self.party.vat_number: nro_doc = self.party.vat_number if len(nro_doc) < 11: tipo_doc = 96 # DNI else: tipo_doc = 80 # CUIT else: nro_doc = "0" # only "consumidor final" tipo_doc = 99 # consumidor final # invoice amount totals: imp_total = str("%.2f" % abs(self.total_amount)) imp_tot_conc = "0.00" imp_neto = str("%.2f" % abs(self.untaxed_amount)) imp_iva = str("%.2f" % abs(self.tax_amount)) imp_subtotal = imp_neto # TODO: not allways the case! imp_trib = "0.00" imp_op_ex = "0.00" if self.currency.code == 'ARS': moneda_id = "PES" moneda_ctz = 1 else: moneda_id = {'USD': 'DOL'}[self.currency.code] ctz = 1 / self.currency.rate moneda_ctz = str("%.2f" % ctz) # foreign trade data: export permit, country code, etc.: if self.pyafipws_incoterms: incoterms = self.pyafipws_incoterms incoterms_ds = dict(self._fields['pyafipws_incoterms'].selection)[ self.pyafipws_incoterms] else: incoterms = incoterms_ds = None if incoterms == None and incoterms_ds == None and service == 'wsfex': self.raise_user_error('missing_pyafipws_incoterms') if int(tipo_cbte) == 19 and tipo_expo == 1: permiso_existente = "N" or "S" # not used now else: permiso_existente = "" obs_generales = self.comment if self.payment_term: forma_pago = self.payment_term.name obs_comerciales = self.payment_term.name else: forma_pago = obs_comerciales = None idioma_cbte = 1 # invoice language: spanish / español # customer data (foreign trade): nombre_cliente = self.party.name if self.party.vat_number: if self.party.vat_country == "AR": # use the Argentina AFIP's global CUIT for the country: cuit_pais_cliente = self.party.vat_number id_impositivo = None else: # use the VAT number directly id_impositivo = self.party.vat_number # TODO: the prefix could be used to map the customer country cuit_pais_cliente = None else: cuit_pais_cliente = id_impositivo = None if self.invoice_address: address = self.invoice_address domicilio_cliente = " - ".join([ address.name or '', address.street or '', address.streetbis or '', address.zip or '', address.city or '', ]) else: domicilio_cliente = "" if self.invoice_address.country: # map ISO country code to AFIP destination country code: pais_dst_cmp = { 'ar': 200, 'bo': 202, 'br': 203, 'ca': 204, 'co': 205, 'cu': 207, 'cl': 208, 'ec': 210, 'us': 212, 'mx': 218, 'py': 221, 'pe': 222, 'uy': 225, 've': 226, 'cn': 310, 'tw': 313, 'in': 315, 'il': 319, 'jp': 320, 'at': 405, 'be': 406, 'dk': 409, 'es': 410, 'fr': 412, 'gr': 413, 'it': 417, 'nl': 423, 'pt': 620, 'uk': 426, 'sz': 430, 'de': 438, 'ru': 444, 'eu': 497, 'cr': '206' }[self.invoice_address.country.code.lower()] # create the invoice internally in the helper if service == 'wsfe': ws.CrearFactura(concepto, tipo_doc, nro_doc, tipo_cbte, punto_vta, cbt_desde, cbt_hasta, imp_total, imp_tot_conc, imp_neto, imp_iva, imp_trib, imp_op_ex, fecha_cbte, fecha_venc_pago, fecha_serv_desde, fecha_serv_hasta, moneda_id, moneda_ctz) elif service == 'wsmtxca': ws.CrearFactura(concepto, tipo_doc, nro_doc, tipo_cbte, punto_vta, cbt_desde, cbt_hasta, imp_total, imp_tot_conc, imp_neto, imp_subtotal, imp_trib, imp_op_ex, fecha_cbte, fecha_venc_pago, fecha_serv_desde, fecha_serv_hasta, moneda_id, moneda_ctz, obs_generales) elif service == 'wsfex': ws.CrearFactura(tipo_cbte, punto_vta, cbte_nro, fecha_cbte, imp_total, tipo_expo, permiso_existente, pais_dst_cmp, nombre_cliente, cuit_pais_cliente, domicilio_cliente, id_impositivo, moneda_id, moneda_ctz, obs_comerciales, obs_generales, forma_pago, incoterms, idioma_cbte, incoterms_ds) # analyze VAT (IVA) and other taxes (tributo): if service in ('wsfe', 'wsmtxca'): for tax_line in self.taxes: tax = tax_line.tax if tax.group.name == "IVA": iva_id = IVA_AFIP_CODE[tax.rate] base_imp = ("%.2f" % abs(tax_line.base)) importe = ("%.2f" % abs(tax_line.amount)) # add the vat detail in the helper ws.AgregarIva(iva_id, base_imp, importe) else: if 'impuesto' in tax_line.tax.name.lower(): tributo_id = 1 # nacional elif 'iibbb' in tax_line.tax.name.lower(): tributo_id = 3 # provincial elif 'tasa' in tax_line.tax.name.lower(): tributo_id = 4 # municipal else: tributo_id = 99 desc = tax_line.name base_imp = ("%.2f" % abs(tax_line.base)) importe = ("%.2f" % abs(tax_line.amount)) alic = "%.2f" % tax_line.base # add the other tax detail in the helper ws.AgregarTributo(tributo_id, desc, base_imp, alic, importe) ## Agrego un item: #codigo = "PRO1" #ds = "Producto Tipo 1 Exportacion MERCOSUR ISO 9001" #qty = 2 #precio = "150.00" #umed = 1 # Ver tabla de parámetros (unidades de medida) #bonif = "50.00" #imp_total = "250.00" # importe total final del artículo # analize line items - invoice detail # umeds # Parametros. Unidades de Medida, etc. # https://code.google.com/p/pyafipws/wiki/WSFEX#WSFEX/RECEX_Parameter_Tables if service in ('wsfex', 'wsmtxca'): for line in self.lines: if line.product: codigo = line.product.code else: codigo = 0 ds = line.description qty = line.quantity umed = 7 # FIXME: (7 - unit) precio = str(line.unit_price) importe_total = str(line.amount) bonif = None # line.discount #for tax in line.taxes: # if tax.group.name == "IVA": # iva_id = IVA_AFIP_CODE[tax.rate] # imp_iva = importe * tax.rate #if service == 'wsmtxca': # ws.AgregarItem(u_mtx, cod_mtx, codigo, ds, qty, umed, # precio, bonif, iva_id, imp_iva, importe+imp_iva) if service == 'wsfex': ws.AgregarItem(codigo, ds, qty, umed, precio, importe_total, bonif) # Request the authorization! (call the AFIP webservice method) try: if service == 'wsfe': ws.CAESolicitar() vto = ws.Vencimiento elif service == 'wsmtxca': ws.AutorizarComprobante() vto = ws.Vencimiento elif service == 'wsfex': ws.Authorize(self.id) vto = ws.FchVencCAE #except SoapFault as fault: # msg = 'Falla SOAP %s: %s' % (fault.faultcode, fault.faultstring) except Exception, e: if ws.Excepcion: # get the exception already parsed by the helper #import ipdb; ipdb.set_trace() # XXX BREAKPOINT msg = ws.Excepcion + ' ' + str(e) else: # avoid encoding problem when reporting exceptions to the user: import traceback import sys msg = traceback.format_exception_only(sys.exc_type, sys.exc_value)[0]
def get(self, cr, uid, ids, context={}): #invoice = self.pool.get('account.invoice') for wiz in self.browse(cr, uid, ids): company = wiz.journal.company_id tipo_cbte = wiz.journal.pyafipws_invoice_type punto_vta = wiz.journal.pyafipws_point_of_sale service = wiz.journal.pyafipws_electronic_invoice_service # check if it is an electronic invoice sale point: if not tipo_cbte or not punto_vta or not service: raise osv.except_osv('Error !', "Solo factura electrónica") # authenticate against AFIP: auth_data = company.pyafipws_authenticate(service=service) # create the proxy and get the configuration system parameters: cfg = self.pool.get('ir.config_parameter') cache = cfg.get_param(cr, uid, 'pyafipws.cache', context=context) proxy = cfg.get_param(cr, uid, 'pyafipws.proxy', context=context) wsdl = cfg.get_param(cr, uid, 'pyafipws.%s.url' % service, context=context) # import the AFIP webservice helper for electronic invoice if service == 'wsfe': from pyafipws.wsfev1 import WSFEv1, SoapFault # local market ws = WSFEv1() elif service == 'wsmtxca': from pyafipws.wsmtx import WSMTXCA, SoapFault # local + detail wsdl = cfg.get_param(cr, uid, 'pyafipws.wsmtxca.url', context=context) ws = WSMTXCA() elif service == 'wsfex': from pyafipws.wsfexv1 import WSFEXv1, SoapFault # foreign trade wsdl = cfg.get_param(cr, uid, 'pyafipws.wsfex.url', context=context) ws = WSFEXv1() else: raise osv.except_osv('Error !', "%s no soportado" % service) # connect to the webservice and call to the test method ws.Conectar(cache or "", wsdl or "", proxy or "") # set AFIP webservice credentials: ws.Cuit = company.pyafipws_cuit ws.Token = auth_data['token'] ws.Sign = auth_data['sign'] if service in ('wsfe', 'wsmtxca'): if not wiz.cbte_nro: wiz.cbte_nro = ws.CompUltimoAutorizado( tipo_cbte, punto_vta) ws.CompConsultar(tipo_cbte, punto_vta, wiz.cbte_nro) vat = ws.ImptoLiq else: if not wiz.cbte_nro: wiz.cbte_nro = ws.GetLastCMP(tipo_cbte, punto_vta) ws.GetCMP(tipo_cbte, punto_vta, wiz.cbte_nro) vat = 0 # update the form fields with the values returned from AFIP: self.write(cr, uid, ids, { 'cae': ws.CAE, 'cae_due': ws.Vencimiento, 'total': ws.ImpTotal or 0, 'vat': vat, 'cbte_nro': ws.CbteNro, }, context=context) return { 'type': 'ir.actions.act_window', 'res_model': 'pyafipws.invoice.wizard', 'view_mode': 'form', 'view_type': 'form', 'res_id': wiz.id, 'views': [(False, 'form')], 'target': 'new', }
def do_pyafipws_request_cae(self, cr, uid, ids, context=None, *args): "Request to AFIP the invoices' Authorization Electronic Code (CAE)" for invoice in self.browse(cr, uid, ids): # if already authorized (electronic invoice with CAE), ignore if invoice.pyafipws_cae: continue # get the electronic invoice type, point of sale and service: journal = invoice.journal_id company = journal.company_id tipo_cbte = journal.pyafipws_invoice_type punto_vta = journal.pyafipws_point_of_sale service = journal.pyafipws_electronic_invoice_service # check if it is an electronic invoice sale point: if not tipo_cbte or not punto_vta or not service: continue # authenticate against AFIP: auth_data = company.pyafipws_authenticate(service=service) # create the proxy and get the configuration system parameters: cfg = self.pool.get('ir.config_parameter') cache = cfg.get_param(cr, uid, 'pyafipws.cache', context=context) proxy = cfg.get_param(cr, uid, 'pyafipws.proxy', context=context) wsdl = cfg.get_param(cr, uid, 'pyafipws.%s.url' % service, context=context) # import the AFIP webservice helper for electronic invoice if service == 'wsfe': from pyafipws.wsfev1 import WSFEv1 # local market ws = WSFEv1() elif service == 'wsmtxca': from pyafipws.wsmtx import WSMTXCA # local + detail wsdl = cfg.get_param(cr, uid, 'pyafipws.wsmtxca.url', context=context) ws = WSMTXCA() elif service == 'wsfex': from pyafipws.wsfexv1 import WSFEXv1 wsdl = cfg.get_param(cr, uid, 'pyafipws.wsfex.url', context=context) ws = WSFEXv1() else: raise osv.except_osv('Error !', "%s no soportado" % service) from pyafipws.utils import SoapFault # connect to the webservice and call to the test method ws.Conectar(cache or "", wsdl or "", proxy or "") # set AFIP webservice credentials: ws.Cuit = company.pyafipws_cuit ws.Token = auth_data['token'] ws.Sign = auth_data['sign'] # get the last 8 digit of the invoice number cbte_nro = int(invoice.number[-8:]) # get the last invoice number registered in AFIP if service == "wsfe" or service == "wsmtxca": cbte_nro_afip = ws.CompUltimoAutorizado(tipo_cbte, punto_vta) elif service == 'wsfex': cbte_nro_afip = ws.GetLastCMP(tipo_cbte, punto_vta) cbte_nro_next = int(cbte_nro_afip or 0) + 1 # verify that the invoice is the next one to be registered in AFIP if cbte_nro != cbte_nro_next: raise osv.except_osv( u'Error !', u'Referencia: %s \n' u'El número del comprobante debería ser %s y no %s' % (str(invoice.number), str(cbte_nro_next), str(cbte_nro))) # invoice number range (from - to) and date: cbte_nro = cbt_desde = cbt_hasta = cbte_nro_next fecha_cbte = invoice.date_invoice if service != 'wsmtxca': fecha_cbte = fecha_cbte.replace("-", "") # due and billing dates only for concept "services" concepto = tipo_expo = int(invoice.pyafipws_concept or 0) if int(concepto) != 1: fecha_venc_pago = invoice.date_invoice if service != 'wsmtxca': fecha_venc_pago = fecha_venc_pago.replace("-", "") if invoice.pyafipws_billing_start_date: fecha_serv_desde = invoice.pyafipws_billing_start_date if service != 'wsmtxca': fecha_serv_desde = fecha_serv_desde.replace("-", "") else: fecha_serv_desde = None if invoice.pyafipws_billing_end_date: fecha_serv_hasta = invoice.pyafipws_billing_end_date if service != 'wsmtxca': fecha_serv_desde = fecha_serv_desde.replace("-", "") else: fecha_serv_hasta = None else: fecha_venc_pago = fecha_serv_desde = fecha_serv_hasta = None # customer tax number: if invoice.partner_id.vat: nro_doc = invoice.partner_id.vat.replace("-", "") else: nro_doc = "0" # only "consumidor final" tipo_doc = None if nro_doc.startswith("AR"): nro_doc = nro_doc[2:] if int(nro_doc) == 0: tipo_doc = 99 # consumidor final elif len(nro_doc) < 11: tipo_doc = 96 # DNI else: tipo_doc = 80 # CUIT # invoice amount totals: imp_total = str("%.2f" % abs(invoice.amount_total)) imp_tot_conc = "0.00" imp_neto = str("%.2f" % abs(invoice.amount_untaxed)) imp_iva = str("%.2f" % abs(invoice.amount_tax)) imp_subtotal = imp_neto # TODO: not allways the case! imp_trib = "0.00" imp_op_ex = "0.00" if invoice.currency_id.name == 'ARS': moneda_id = "PES" moneda_ctz = 1 else: moneda_id = {'USD': 'DOL'}[invoice.currency_id.name] moneda_ctz = str(invoice.currency_id.rate) # foreign trade data: export permit, country code, etc.: if False: ##invoice.pyafipws_incoterms: incoterms = invoice.pyafipws_incoterms.code incoterms_ds = invoice.pyafipws_incoterms.name else: incoterms = incoterms_ds = None if int(tipo_cbte) == 19 and tipo_expo == 1: permiso_existente = "N" or "S" # not used now else: permiso_existente = "" obs_generales = invoice.comment if invoice.payment_term: forma_pago = invoice.payment_term.name obs_comerciales = invoice.payment_term.name else: forma_pago = obs_comerciales = None idioma_cbte = 1 # invoice language: spanish / español # customer data (foreign trade): nombre_cliente = invoice.partner_id.name if invoice.partner_id.vat: if invoice.partner_id.vat.startswith("AR"): # use the Argentina AFIP's global CUIT for the country: cuit_pais_cliente = invoice.partner_id.vat[2:] id_impositivo = None else: # use the VAT number directly id_impositivo = invoice.partner_id.vat[2:] # TODO: the prefix could be used to map the customer country cuit_pais_cliente = None else: cuit_pais_cliente = id_impositivo = None # OpenERP 7 no tiene address_invoice_id if invoice.partner_id: domicilio_cliente = " - ".join([ invoice.partner_id.name or '', invoice.partner_id.street or '', invoice.partner_id.street2 or '', invoice.partner_id.zip or '', invoice.partner_id.city or '', ]) else: domicilio_cliente = "" if invoice.partner_id.country_id: # map ISO country code to AFIP destination country code: iso_code = invoice.partner_id.country_id.code.lower() pais_dst_cmp = AFIP_COUNTRY_CODE_MAP[iso_code] # create the invoice internally in the helper if service == 'wsfe': ws.CrearFactura(concepto, tipo_doc, nro_doc, tipo_cbte, punto_vta, cbt_desde, cbt_hasta, imp_total, imp_tot_conc, imp_neto, imp_iva, imp_trib, imp_op_ex, fecha_cbte, fecha_venc_pago, fecha_serv_desde, fecha_serv_hasta, moneda_id, moneda_ctz) elif service == 'wsmtxca': ws.CrearFactura(concepto, tipo_doc, nro_doc, tipo_cbte, punto_vta, cbt_desde, cbt_hasta, imp_total, imp_tot_conc, imp_neto, imp_subtotal, imp_trib, imp_op_ex, fecha_cbte, fecha_venc_pago, fecha_serv_desde, fecha_serv_hasta, moneda_id, moneda_ctz, obs_generales) elif service == 'wsfex': ws.CrearFactura(tipo_cbte, punto_vta, cbte_nro, fecha_cbte, imp_total, tipo_expo, permiso_existente, pais_dst_cmp, nombre_cliente, cuit_pais_cliente, domicilio_cliente, id_impositivo, moneda_id, moneda_ctz, obs_comerciales, obs_generales, forma_pago, incoterms, idioma_cbte, incoterms_ds) # analyze VAT (IVA) and other taxes (tributo): if service in ('wsfe', 'wsmtxca'): for tax_line in invoice.tax_line: if "IVA" in tax_line.name: if '0%' in tax_line.name: iva_id = 3 elif '10,5%' in tax_line.name: iva_id = 4 elif '21%' in tax_line.name: iva_id = 5 elif '27%' in tax_line.name: iva_id = 6 else: iva_id = 0 base_imp = ("%.2f" % abs(tax_line.base)) importe = ("%.2f" % abs(tax_line.amount)) # add the vat detail in the helper ws.AgregarIva(iva_id, base_imp, importe) else: if 'impuesto' in tax_line.name.lower(): tributo_id = 1 # nacional elif 'iibbb' in tax_line.name.lower(): tributo_id = 3 # provincial elif 'tasa' in tax_line.name.lower(): tributo_id = 4 # municipal else: tributo_id = 99 desc = tax_line.name base_imp = ("%.2f" % abs(tax_line.base)) importe = ("%.2f" % abs(tax_line.amount)) alic = "%.2f" % tax_line.base # add the other tax detail in the helper ws.AgregarTributo(id, desc, base_imp, alic, importe) # analize line items - invoice detail if service in ('wsfex', 'wsmtxca'): for line in invoice.invoice_line: codigo = line.product_id.code u_mtx = 1 # TODO: get it from uom? cod_mtx = line.product_id.ean13 ds = line.name qty = line.quantity umed = 7 # TODO: line.uos_id...? precio = line.price_unit importe = line.price_subtotal bonif = line.discount or None if line.invoice_line_tax_id: iva_id = 5 # TODO: line.tax_code_id? imp_iva = importe * line.invoice_line_tax_id[0].amount else: iva_id = 1 imp_iva = 0 if service == 'wsmtxca': ws.AgregarItem(u_mtx, cod_mtx, codigo, ds, qty, umed, precio, bonif, iva_id, imp_iva, importe + imp_iva) elif service == 'wsfex': ws.AgregarItem(codigo, ds, qty, umed, precio, importe, bonif) # Request the authorization! (call the AFIP webservice method) vto = None try: if service == 'wsfe': ws.CAESolicitar() vto = ws.Vencimiento elif service == 'wsmtxca': ws.AutorizarComprobante() vto = ws.Vencimiento elif service == 'wsfex': ws.Authorize(invoice.id) vto = ws.FchVencCAE except SoapFault as fault: msg = 'Falla SOAP %s: %s' % (fault.faultcode, fault.faultstring) except Exception, e: if ws.Excepcion: # get the exception already parsed by the helper msg = ws.Excepcion else: # avoid encoding problem when reporting exceptions to the user: msg = traceback.format_exception_only( sys.exc_type, sys.exc_value)[0] else: msg = u"\n".join([ws.Obs or "", ws.ErrMsg or ""]) # calculate the barcode: if ws.CAE: cae_due = ''.join([c for c in str(vto or '') if c.isdigit()]) bars = ''.join([ str(ws.Cuit), "%02d" % int(tipo_cbte), "%04d" % int(punto_vta), str(ws.CAE), cae_due ]) bars = bars + self.pyafipws_verification_digit_modulo10(bars) else: bars = "" # store the results self.write( cr, uid, invoice.id, { 'pyafipws_cae': ws.CAE, 'pyafipws_cae_due_date': vto or None, 'pyafipws_result': ws.Resultado, 'pyafipws_message': msg, 'pyafipws_xml_request': ws.XmlRequest, 'pyafipws_xml_response': ws.XmlResponse, 'pyafipws_barcode': bars, })
import sys import os import datetime import pytest from pyafipws.wsaa import WSAA from pyafipws.wsfexv1 import WSFEXv1, main import future from builtins import str __author__ = "Mariano Reingart <*****@*****.**>" __copyright__ = "Copyright (C) 2010-2019 Mariano Reingart" __license__ = "GPL 3.0" __WSDL__ = "https://wswhomo.afip.gov.ar/wsfexv1/service.asmx?WSDL" __obj__ = WSFEXv1() __service__= "wsfex" CUIT = 20267565393 CERT = "reingart.crt" PKEY = "reingart.key" CACERT = "conf/afip_ca_info.crt" CACHE = "" # Debido a que Python solicita una opción de diseño, hay una advertencia # sobre una conexión no cerrada al ejecutar las pruebas. # https://github.com/kennethreitz/requests/issues/3912 # Esto puede ser molesto al ejecutar las pruebas, por lo tanto, # suprimir la advertencia como se discute en # https://github.com/kennethreitz/requests/issues/1882