Example #1
0
    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
Example #2
0
 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 {}
Example #3
0
    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()
Example #5
0
 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
Example #6
0
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
Example #7
0
 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
Example #8
0
    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,
                })
Example #11
0
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