Exemplo n.º 1
0
def _get_afip():
    """Build and authenticate AFIP structure."""
    # AFIP init
    wsaa = WSAA()
    wsfev1 = WSFEv1()

    # get access ticket (token y sign)
    certificate = settings.AFIP['auth_cert_path']
    private_key = settings.AFIP['auth_key_path']
    if not os.path.exists(certificate):
        raise ValueError(
            "Auth certificate can not be found (got {!r})".format(certificate))
    if not os.path.exists(private_key):
        raise ValueError(
            "Auth key can not be found (got {!r})".format(private_key))
    ta = wsaa.Autenticar("wsfe",
                         certificate,
                         private_key,
                         wsdl=settings.AFIP['url_wsaa'],
                         cache=CACHE,
                         debug=True)
    wsfev1.Cuit = settings.AFIP['cuit']
    wsfev1.SetTicketAcceso(ta)
    wsfev1.Conectar(CACHE, settings.AFIP['url_wsfev1'])
    return wsfev1
Exemplo n.º 2
0
def auth(request):
    if 'dontusefix' in request.keywords:
        return
    z = request.module.__obj__
    z.Cuit = CUIT
    wsaa = WSAA()
    ta = wsaa.Autenticar(request.module.__service__, CERT, PKEY)
    z.SetTicketAcceso(ta)
    z.Conectar(CACHE, request.module.__WSDL__)
    return z
Exemplo n.º 3
0
Arquivo: afip.py Projeto: cedir/web
class _Afip(object):
    '''
    Clase que abstrae la emision de comprobantes electronicos en la afip.
    '''
    def __init__(self, privada, certificado, cuit):
        # instanciar el componente para factura electrónica mercado interno
        self.webservice = WSFEv1()
        self.webservice.LanzarExcepciones = True

        # datos de conexión (cambiar URL para producción)
        cache = None
        wsdl = AFIP_WSDL_URL
        proxy = ""
        wrapper = ""
        cacert = None

        # conectar
        try:
            self.webservice.Conectar(cache, wsdl, proxy, wrapper, cacert)
        except (ExpatError, ServerNotFoundError, SoapFault):
            raise AfipErrorRed("Error en la conexion inicial con la AFIP.")

        self.cert = certificado       # archivos a tramitar previamente ante AFIP
        self.clave = privada
        self.wsaa_url = AFIP_WSAA_URL
        self.wsaa = WSAA()
        self.autenticar()

        self.webservice.Cuit = cuit

    def autenticar(self):
        '''
        Pide un ticket de acceso a la AFIP que sera usado en todas las requests.
        '''
        try:
            self.ticket_autenticacion = self.wsaa.Autenticar(
                "wsfe", self.cert, self.clave, self.wsaa_url, cache=CACHE_PATH, debug=True)
        except SoapFault as e:
            raise AfipErrorRed("Error autenticando en la Afip: " + str(e))
        if not self.ticket_autenticacion and self.wsaa.Excepcion:
            raise AfipError("Error WSAA: %s" % self.wsaa.Excepcion)

        # establecer credenciales (token y sign):
        self.webservice.SetTicketAcceso(self.ticket_autenticacion)

    @requiere_ticket
    def emitir_comprobante(self, comprobante_cedir, lineas):
        '''
        Toma un comprobante nuestro y una lista de lineas, lo traduce al formato que usa la AFIP en su webservice
        y trata de emitirlo.
        En caso de exito, setea las propiedades faltantes del comprobante que son dependientes
        de la AFIP.
        En caso de error, levanta una excepcion.
        '''
        nro = self.consultar_proximo_numero(comprobante_cedir.nro_terminal, comprobante_cedir.tipo_comprobante, comprobante_cedir.sub_tipo)
        fecha = comprobante_cedir.fecha_emision.strftime("%Y%m%d")
        # En estos tipos de comprobante en especifico, la AFIP te prohibe poner un campo fecha de vencimiento.
        fecha_vto = None if comprobante_cedir.tipo_comprobante.id in [ID_TIPO_COMPROBANTE_NOTA_DE_DEBITO_ELECTRONICA, ID_TIPO_COMPROBANTE_NOTA_DE_CREDITO_ELECTRONICA] else comprobante_cedir.fecha_vencimiento.strftime("%Y%m%d")
        imp_iva = sum([l.iva for l in lineas])
        if comprobante_cedir.gravado.id == IVA_EXCENTO:
            imp_neto = Decimal("0.00")
            imp_op_ex = sum([l.importe_neto for l in lineas])
        else:
            # importe neto gravado (todas las alicuotas)
            imp_neto = sum([l.importe_neto for l in lineas])
            imp_op_ex = Decimal("0.00")        # importe total operaciones exentas

        self.webservice.CrearFactura(
            concepto=2,  # 2 es servicios, lo unico que hace el cedir.
            tipo_doc=comprobante_cedir.tipo_id_afip,
            nro_doc=comprobante_cedir.nro_id_afip,
            tipo_cbte=comprobante_cedir.codigo_afip,
            punto_vta=comprobante_cedir.nro_terminal,
            cbt_desde=nro,
            cbt_hasta=nro,
            imp_total=Decimal(comprobante_cedir.total_facturado).quantize(Decimal('.01'), ROUND_UP),
            imp_neto=Decimal(imp_neto).quantize(Decimal('.01'), ROUND_UP),
            imp_iva=Decimal(imp_iva).quantize(Decimal('.01'), ROUND_UP),
            imp_op_ex=Decimal(imp_op_ex).quantize(Decimal('.01'), ROUND_UP),
            fecha_cbte=fecha, # Estas fechas no cambian nunca, pero son requisito de la AFIP para el concepto=2
            fecha_serv_desde=fecha,
            fecha_serv_hasta=fecha,
            fecha_venc_pago=fecha_vto)

        # Agregar el IVA
        if comprobante_cedir.gravado.id == IVA_10_5:
            self.webservice.AgregarIva(
                iva_id=4,
                base_imp=Decimal(imp_neto).quantize(Decimal('.01'), ROUND_UP),
                importe=Decimal(imp_iva).quantize(Decimal('.01'), ROUND_UP))
        elif comprobante_cedir.gravado.id == IVA_21:
            self.webservice.AgregarIva(
                iva_id=5,
                base_imp=Decimal(imp_neto).quantize(Decimal('.01'), ROUND_UP),
                importe=Decimal(imp_iva).quantize(Decimal('.01'), ROUND_UP))

        # Si hay comprobantes asociados, los agregamos.
        if comprobante_cedir.tipo_comprobante.id in [
            ID_TIPO_COMPROBANTE_NOTA_DE_DEBITO, # Para comprobantes no electronicos puede no ser necesario pero se los deja por completitud
            ID_TIPO_COMPROBANTE_NOTA_DE_CREDITO,
            ID_TIPO_COMPROBANTE_NOTA_DE_DEBITO_ELECTRONICA,
            ID_TIPO_COMPROBANTE_NOTA_DE_CREDITO_ELECTRONICA] and comprobante_cedir.factura:
            comprobante_asociado = comprobante_cedir.factura
            self.webservice.AgregarCmpAsoc(
                tipo=comprobante_asociado.codigo_afip,
                pto_vta=comprobante_asociado.nro_terminal,
                nro=comprobante_asociado.numero,
                cuit=self.webservice.Cuit, # Cuit emisor.
                fecha=comprobante_asociado.fecha_emision.strftime("%Y%m%d")
            )

        # Si es Factura de Credito Electronica, hayq eu agregar como opcional el CBU del Cedir
        # y el opcional Sistema de Circulacion Abierta
        if comprobante_cedir.tipo_comprobante.id in [
            ID_TIPO_COMPROBANTE_FACTURA_CREDITO_ELECTRONICA]:
            self.webservice.AgregarOpcional(2101, "0150506102000109564632")
            self.webservice.AgregarOpcional(27, 'SCA')

        # Si es Nota de Debito/Credito Electronica, hay que agregar un opcional indicando que no es anulacion.
        # En principio, el Cedir nunca anula facturas.
        if comprobante_cedir.tipo_comprobante.id in [
            ID_TIPO_COMPROBANTE_NOTA_DE_DEBITO_ELECTRONICA,
            ID_TIPO_COMPROBANTE_NOTA_DE_CREDITO_ELECTRONICA]:
            self.webservice.AgregarOpcional(22, "N")

        # llamar al webservice de AFIP para autorizar la factura y obtener CAE:
        try:
            self.webservice.CAESolicitar()
        except (ExpatError, ServerNotFoundError, SoapFault):
            raise AfipErrorRed("Error de red emitiendo el comprobante.")
        if self.webservice.Resultado == "R":
            # Si la AFIP nos rechaza el comprobante, lanzamos excepcion.
            raise AfipErrorValidacion(self.webservice.ErrMsg or self.webservice.Obs)
        if self.webservice.Resultado == "O":
            # Si hay observaciones (en self.webservice.Obs), deberiamos logearlas en la DB.
            pass

        comprobante_cedir.cae = self.webservice.CAE
        comprobante_cedir.numero = nro

        if self.webservice.Vencimiento:
            comprobante_cedir.vencimiento_cae = datetime.strptime(self.webservice.Vencimiento,'%Y%m%d').date()

    @requiere_ticket
    def consultar_comprobante(self, comprobante):
        '''
        Consulta que informacion tiene la AFIP sobre un comprobante nuestro.
        Devuelve un diccionario con todos los datos.
        '''
        codigo_afip_tipo = comprobante.codigo_afip
        nro_terminal = comprobante.nro_terminal
        cbte_nro = comprobante.numero
        self.webservice.CompConsultar(codigo_afip_tipo, nro_terminal, cbte_nro)
        # Todos estos datos se setean en el objeto afip cuando la llamada a ConsultarComprobante es exitosa.
        # Notar que si falla (comprobante invalido, conexion...) queda con valores viejos!
        return {
            "fecha": self.webservice.FechaCbte,
            "numero": self.webservice.CbteNro,
            "punto_venta": self.webservice.PuntoVenta,
            "vencimiento": self.webservice.Vencimiento,
            "importe_total": self.webservice.ImpTotal,
            "CAE": self.webservice.CAE,
            "emision_tipo": self.webservice.EmisionTipo
        }

    @requiere_ticket
    def consultar_proximo_numero(self, nro_terminal, tipo_comprobante, sub_tipo):
        codigo_afip = Comprobante(nro_terminal=nro_terminal, tipo_comprobante=tipo_comprobante, sub_tipo=sub_tipo).codigo_afip
        return int(self.webservice.CompUltimoAutorizado(codigo_afip, nro_terminal) or 0) + 1
Exemplo n.º 4
0
def facturar(registros):
    """Rutina para emitir facturas electrónicas en PDF c/CAE AFIP Argentina"""

    # inicialización AFIP:
    wsaa = WSAA()
    wsfev1 = WSFEv1()
    # obtener ticket de acceso (token y sign):
    ta = wsaa.Autenticar(
        "wsfe", CERT, PRIVATEKEY, wsdl=URL_WSAA, cache=CACHE, debug=True
    )
    wsfev1.Cuit = CUIT
    wsfev1.SetTicketAcceso(ta)
    wsfev1.Conectar(CACHE, URL_WSFEv1)

    # inicialización PDF
    fepdf = FEPDF()
    fepdf.CargarFormato("factura.csv")
    fepdf.FmtCantidad = "0.2"
    fepdf.FmtPrecio = "0.2"
    fepdf.CUIT = CUIT
    for k, v in CONF_PDF.items():
        fepdf.AgregarDato(k, v)

    if "h**o" in URL_WSAA:
        fepdf.AgregarCampo(
            "DEMO",
            "T",
            120,
            260,
            0,
            0,
            text="DEMOSTRACION",
            size=70,
            rotate=45,
            foreground=0x808080,
            priority=-1,
        )
        fepdf.AgregarDato("motivos_obs", "Ejemplo Sin validez fiscal")

    # recorrer los registros a facturar, solicitar CAE y generar el PDF:
    for reg in registros:
        hoy = datetime.date.today().strftime("%Y%m%d")
        cbte = Comprobante(
            tipo_cbte=6,
            punto_vta=4000,
            fecha_cbte=hoy,
            cbte_nro=reg.get("nro"),
            tipo_doc=96,
            nro_doc=reg["dni"],
            nombre_cliente=reg["nombre"],  # "Juan Perez"
            domicilio_cliente=reg["domicilio"],  # "Balcarce 50"
            fecha_serv_desde=reg.get("periodo_desde"),
            fecha_serv_hasta=reg.get("periodo_hasta"),
            fecha_venc_pago=reg.get("venc_pago", hoy),
        )
        cbte.agregar_item(
            ds=reg["descripcion"],
            qty=reg.get("cantidad", 1),
            precio=reg.get("precio", 0),
            tasa_iva=reg.get("tasa_iva", 21.0),
        )
        ok = cbte.autorizar(wsfev1)
        nro = cbte.encabezado["cbte_nro"]
        print("Factura autorizada", nro, cbte.encabezado["cae"])
        if "h**o" in URL_WSFEv1:
            cbte.encabezado["motivos_obs"] = "Ejemplo Sin validez fiscal"
        ok = cbte.generar_pdf(fepdf, "/tmp/factura_{}.pdf".format(nro))
        print("PDF generado", ok)
Exemplo n.º 5
0
# Desde la versión 2.07 de PyAfipWs se puede usar el método Autenticar()
#
# https://www.sistemasagiles.com.ar/trac/wiki/ManualPyAfipWs#M%C3%A9todos
# ------------------------------------------------------------------------
wsaa_url = 'https://wsaa.afip.gov.ar/ws/services/LoginCms'

# solo usar si hay servidor intermedio
proxy = ""
# httplib2 (default), pycurl (depende proxy)
wrapper = ""
# autoridades certificantes (servidores)
cacert = "pyafipws/conf/afip_ca_info.crt"
# Directorio para archivos temporales (dejar en blanco para usar predeterminado)
cache = "pyafipws/cache"

ta = wsaa.Autenticar(SERVICIO, CERTIFICADO, CLAVEPRIVADA, wsaa_url, proxy, wrapper, cacert, cache)

# utilizar las credenciales:
#print wsaa.Token
#print wsaa.Sign

#wsaa.SetTicketAcceso(ta)

# conectar al webservice de padrón:
padron = WSSrPadronA5()
padron.SetTicketAcceso(ta)
padron.Cuit = "20267268038"
padron.Conectar(
    wsdl="https://aws.afip.gov.ar/sr-padron/webservices/personaServiceA5?wsdl"
)
Exemplo n.º 6
0
def generate_invoices(records):
    """Generate the invoices in PDF using AFIP API resources."""
    # AFIP init
    wsaa = WSAA()
    wsfev1 = WSFEv1()

    # get access ticket (token y sign)
    certificate = settings.AFIP['auth_cert_path']
    private_key = settings.AFIP['auth_key_path']
    if not os.path.exists(certificate):
        raise ValueError(
            "Auth certificate can not be found (got {!r})".format(certificate))
    if not os.path.exists(private_key):
        raise ValueError(
            "Auth key can not be found (got {!r})".format(private_key))
    ta = wsaa.Autenticar("wsfe",
                         certificate,
                         private_key,
                         wsdl=settings.AFIP['url_wsaa'],
                         cache=CACHE,
                         debug=True)
    wsfev1.Cuit = settings.AFIP['cuit']
    wsfev1.SetTicketAcceso(ta)
    wsfev1.Conectar(CACHE, settings.AFIP['url_wsfev1'])

    # init PDF builder
    fepdf = FEPDF()
    fepdf.CargarFormato("factura.csv")
    fepdf.FmtCantidad = "0.2"
    fepdf.FmtPrecio = "0.2"
    fepdf.CUIT = settings.AFIP['cuit']
    for k, v in CONFIG_PDF.items():
        fepdf.AgregarDato(k, v)

    # safeguard when using test webservice endpoints
    if "h**o" in settings.AFIP['url_wsaa']:
        fepdf.AgregarCampo("DEMO",
                           'T',
                           120,
                           260,
                           0,
                           0,
                           text="DEMOSTRACION",
                           size=70,
                           rotate=45,
                           foreground=0x808080,
                           priority=-1)
        fepdf.AgregarDato("motivos_obs", "Ejemplo Sin Validez Fiscal")

    # get CAE for each record and generate corresponding PDF
    results = {}
    for record in records:
        invoice = MemberInvoice(document_number=record['dni'],
                                fullname=record['fullname'],
                                address=record['address'],
                                city=record['city'],
                                zip_code=record['zip_code'],
                                province=record['province'],
                                invoice_date=record['invoice_date'],
                                invoice_number=record['invoice'],
                                service_date_from=record['service_date_from'],
                                service_date_to=record['service_date_to'])
        invoice.add_item(description=record['description'],
                         quantity=record['quantity'],
                         amount=record['amount'],
                         comment=record['payment_comment'])

        authorized_ok = invoice.autorizar(wsfev1)
        invoice_number = invoice.header["cbte_nro"]
        print("    invoice generated: number={} CAE={} authorized={}".format(
            invoice_number, invoice.header["cae"], authorized_ok))
        results[invoice_number] = {'invoice_ok': authorized_ok}
        if not authorized_ok:
            print("WARNING not auth")
            return

        # another safeguard
        if "h**o" in settings.AFIP['url_wsfev1']:
            invoice.header["motivos_obs"] = "Ejemplo Sin validez fiscal"

        # generate the PDF
        pdf_name = "FacturaPyArAC-{:04d}-{:08d}.pdf".format(
            settings.AFIP['selling_point'], invoice_number)
        pdf_path = os.path.join(PDF_PATH, pdf_name)
        invoice.generate_pdf(fepdf, pdf_path)
        print("    PDF generated {!r}".format(pdf_path))
        results[invoice_number]['pdf_path'] = pdf_path

    return results