Operación que realiza consulta de CTGs según el criterio ingresado.
344928
def ConsultarCTG(self, numero_carta_de_porte=None, numero_ctg=None, 
                     patente=None, cuit_solicitante=None, cuit_destino=None,
                     fecha_emision_desde=None, fecha_emision_hasta=None):
        ""
        ret = self.client.consultarCTG(request=dict(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuitRepresentado': self.Cuit, },
                        consultarCTGDatos=dict(
                            cartaPorte=numero_carta_de_porte, 
                            ctg=numero_ctg,
                            patente=patente,
                            cuitSolicitante=cuit_solicitante,
                            cuitDestino=cuit_destino,
                            fechaEmisionDesde=fecha_emision_desde,
                            fechaEmisionHasta=fecha_emision_hasta,
                            )))['response']
        self.__analizar_errores(ret)
        datos = ret.get('arrayDatosConsultarCTG')
        if datos:
            self.DatosCTG = datos
            self.LeerDatosCTG(pop=False)
            return True
        else:
            self.DatosCTG = []
        return ''
1207828
def AnularLiquidacionSecundaria(self, coe):
        ""
        ret = self.client.lsgAnular(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuit': self.Cuit, },
                        coe=coe,
                        )
        ret = ret['anulacionReturn']
        self.__analizar_errores(ret)
        self.Resultado = ret['resultado']
        return self.COE
1028957
def AgregarCompraAsociada(self, tipo_cbte, pto_vta, nro_cbte, cant_asoc, nro_item):
        ""
        d = {'tipoComprobante': tipo_cbte, 
             'puntoVenta': pto_vta,
             'nroComprobante': nro_cbte, 
             'nroItem': nro_item,
             'cantidadAsociada': cant_asoc}
        if 'itemDetalleLiquidacion' in self.solicitud:
            item_liq = self.solicitud['itemDetalleLiquidacion'][-1]
            item_liq['liquidacionCompraAsociada'].append(d)
        else:
            item_liq = self.solicitud['itemDetalleAjusteLiquidacion'][-1]
            item_liq['ajusteCompraAsociada'].append(d)
        return True
284556
def AnalizarLiquidacion(self, liq):
        ""
        # proceso los datos básicos de la liquidación (devuelto por consultar):
        if liq:
            cab = liq['encabezado']
            self.CAE = str(cab['cae'])
            self.FechaComprobante = str(cab['fechaComprobante'])
            self.NroComprobante = cab['nroComprobante']
            tot = liq['resumenTotales']
            self.AlicuotaIVA = tot['alicuotaIVA']
            self.TotalNeto = tot['totalNetoLiquidacion']
            self.ImporteIVA = tot['importeIVA']
            self.TotalBonificacionesCalidad = tot['totalBonificacionesCalidad']
            self.TotalPenalizacionesCalidad = tot['totalPenalizacionesCalidad']
            self.TotalBonificacionesComerciales = tot['totalBonificacionesComerciales']
            self.TotalDebitosComerciales = tot['totalDebitosComerciales']
            self.TotalOtrosImpuestos = tot['totalOtrosImpuestos']
            self.Total = tot['totalLiquidacion']

            # parámetros de salida:
            self.params_out = dict(
                tipo_cbte=liq['encabezado']['tipoComprobante'],
                pto_vta=liq['encabezado']['puntoVenta'],
                nro_cbte=liq['encabezado']['nroComprobante'],
                fecha=str(liq['encabezado']['fechaComprobante']),
                cae=str(liq['encabezado']['cae']),
                domicilio_comprador=liq['encabezado']['domicilioComprador'],
                tambero=dict(
                    cuit=liq['tambero']['cuit'],
                    iibb=liq['tambero']['iibb'],
                    razon_social=liq['tambero']['razonSocial'],
                    situacion_iva=liq['tambero']['situacionIVA'],
                    domicilio_fiscal=liq['tambero']['domicilioFiscal'],
                    provincia=liq['tambero']['provincia'],
                    cod_postal=liq['tambero']['codPostal'],
                    ),
                resumen_kg_remitidos=liq['resumenKgRemitidos'],
                alicuota_iva=liq['resumenTotales']['alicuotaIVA'],
                importe_iva=liq['resumenTotales']['importeIVA'],
                total_neto=liq['resumenTotales']['totalNetoLiquidacion'],
                total_bonificaciones_calidad=liq['resumenTotales']['totalBonificacionesCalidad'],
                total_penalizaciones_calidad=liq['resumenTotales']['totalPenalizacionesCalidad'],
                total_bonificaciones_comerciales=liq['resumenTotales']['totalBonificacionesComerciales'],
                total_debitos_comerciales=liq['resumenTotales']['totalDebitosComerciales'],
                total_otros_impuestos=liq['resumenTotales']['totalOtrosImpuestos'],
                total=liq['resumenTotales']['totalLiquidacion'],
                bonificacion_penalizacion=[],
                remitos=[],
                otro_impuesto=[],               
                pdf=liq.get('pdf'),
                )
            for ret in liq.get('bonificacionPenalizacion', []):
                self.params_out['bonificacion_penalizacion'].append(dict(
                    retencion_codigo=ret['codigo'],
                    retencion_importe=ret['importe'],
                    ))
            for trib in liq.get('otroImpuesto',[]):
                self.params_out['otro_impuesto'].append(dict(
                    tributo_descripcion=trib.get('descripcion', ""),
                    tributo_base_imponible=trib['baseImponible'],
                    tributo_alicuota=trib['alicuota'],
                    tributo_codigo=trib['codigo'],
                    tributo_importe=trib['importe'],
                    ))
            if DEBUG:
                import pprint
                pprint.pprint(self.params_out)
        self.params_out['errores'] = self.errores
800757
def CrearAjuste(self, tipo_cbte, pto_vta, nro_cbte, fecha, 
            cod_deposito_acopio=None, tipo_ajuste=None, cuit_receptor=None, 
            iibb_emisor=None, iibb_receptor=None, fecha_inicio_actividad=None,
            **kwargs):
        ""
        # codDepositoAcopio, tipoAjuste, cuitReceptor obligatorio ajustar liq.
        # WSLTVv1.3 fechaLiquidacion/fechaInicioActividad para ajuste físico
        # creo el diccionario con los campos generales de la liquidación:
        liq = dict(tipoComprobante=tipo_cbte, 
                   nroComprobante=nro_cbte, 
                   puntoVenta=pto_vta, 
                   fechaAjusteLiquidacion=fecha, 
                   fechaLiquidacion=fecha,
                   fechaInicioActividad=fecha_inicio_actividad,
                   codDepositoAcopio=cod_deposito_acopio, 
                   tipoAjuste=tipo_ajuste,
                   cuitReceptor=cuit_receptor,
                   iibbReceptor=iibb_receptor,
                   iibbEmisor=iibb_emisor,
                   comprobanteAAjustar=[],
                   )
        self.solicitud = dict(liquidacion=liq,
                              precioClase=[],
                              retencion=[],
                              tributo=[],
                             )
        return True
1031222
def AnalizarLiquidacion(self, aut, liq=None, ajuste=False):
        ""
        # proceso los datos básicos de la liquidación (devuelto por consultar):
        if liq:
            self.params_out = dict(
                        pto_emision=liq.get('ptoEmision'),
                        nro_orden=liq.get('nroOrden'),
                        cuit_comprador=liq.get('cuitComprador'),
                        nro_act_comprador=liq.get('nroActComprador'),
                        nro_ing_bruto_comprador=liq.get('nroIngBrutoComprador'),
                        cod_tipo_operacion=liq.get('codTipoOperacion'),
                        es_liquidacion_propia=liq.get('esLiquidacionPropia'),
                        es_canje=liq.get('esCanje'),
                        cod_puerto=liq.get('codPuerto'),
                        des_puerto_localidad=liq.get('desPuertoLocalidad'),
                        cod_grano=liq.get('codGrano'),
                        cuit_vendedor=liq.get('cuitVendedor'),
                        nro_ing_bruto_vendedor=liq.get('nroIngBrutoVendedor'),
                        actua_corredor=liq.get('actuaCorredor'),
                        liquida_corredor=liq.get('liquidaCorredor'),
                        cuit_corredor=liq.get('cuitCorredor'),
                        comision_corredor=liq.get('comisionCorredor'),
                        nro_ing_bruto_corredor=liq.get('nroIngBrutoCorredor'),
                        fecha_precio_operacion=liq.get('fechaPrecioOperacion'),
                        precio_ref_tn=liq.get('precioRefTn'),
                        cod_grado_ref=liq.get('codGradoRef'),
                        cod_grado_ent=liq.get('codGradoEnt'),
                        factor_ent=liq.get('factorEnt'),
                        precio_flete_tn=liq.get('precioFleteTn'),
                        cont_proteico=liq.get('contProteico'),
                        alic_iva_operacion=liq.get('alicIvaOperacion'),
                        campania_ppal=liq.get('campaniaPPal'),
                        cod_localidad_procedencia=liq.get('codLocalidadProcedencia'),
                        cod_prov_procedencia=liq.get('codProvProcedencia'),
                        datos_adicionales=liq.get('datosAdicionales'),
                        peso_neto_sin_certificado=liq.get('pesoNetoSinCertificado'),
                        cod_localidad_procedencia_sin_certificado=liq.get('codLocalidadProcedenciaSinCertificado'),
                        cod_prov_procedencia_sin_certificado=liq.get('codProvProcedenciaSinCertificado'),
                        certificados=[],
                    )
            if ajuste:
                self.params_out.update(
                        # ajustes:
                        diferencia_peso_neto=liq.get('diferenciaPesoNeto'),
                        diferencia_precio_operacion=liq.get('diferenciaPrecioOperacion'),
                        cod_grado=liq.get('codGrado'),
                        val_grado=liq.get('valGrado'),
                        factor=liq.get('factor'),
                        diferencia_precio_flete_tn=liq.get('diferenciaPrecioFleteTn'),
                        concepto_importe_iva_0=liq.get('conceptoImporteIva0'),
                        importe_ajustar_iva_0=liq.get('importeAjustarIva0'),
                        concepto_importe_iva_105=liq.get('conceptoImporteIva105'),
                        importe_ajustar_iva_105=liq.get('importeAjustarIva105'),
                        concepto_importe_iva_21=liq.get('conceptoImporteIva21'),
                        importe_ajustar_iva_21=liq.get('importeAjustarIva21'),
                    )
                # analizar detalle de importes ajustados discriminados por alicuota
                # (por compatibildiad y consistencia se usan los mismos campos)
                for it in liq.get("importes", liq.get("importe")):
                    # en ajustes LSG no se agrupan los importes en un subtipo...
                    if 'importeReturn' in it:
                        it = it['importeReturn'][0]     # TODO: revisar SOAP
                    tasa = "iva_%s" % str(it['alicuota']).replace(".", "").strip()
                    self.params_out["concepto_importe_%s" % tasa] = it['concepto']
                    self.params_out["importe_ajustar_%s" % tasa] = it['importe']
                    self.params_out["iva_calculado_%s" % tasa] = it['ivaCalculado']
            if 'certificados' in liq:
                for c in liq['certificados']:
                    cert = c['certificado']
                    self.params_out['certificados'].append(dict(
                        tipo_certificado_deposito=cert['tipoCertificadoDeposito'],
                        nro_certificado_deposito=cert['nroCertificadoDeposito'],
                        peso_neto=cert['pesoNeto'],
                        cod_localidad_procedencia=cert['codLocalidadProcedencia'],
                        cod_prov_procedencia=cert['codProvProcedencia'],
                        campania=cert['campania'],
                        fecha_cierre=cert['fechaCierre'],
                    ))

        self.params_out['errores'] = self.errores
            
        # proceso la respuesta de autorizar, ajustar (y consultar):
        if aut:
            self.TotalDeduccion = aut.get('totalDeduccion')
            self.TotalRetencion = aut.get('totalRetencion')
            self.TotalRetencionAfip = aut.get('totalRetencionAfip')
            self.TotalOtrasRetenciones = aut.get('totalOtrasRetenciones')
            self.TotalNetoAPagar = aut.get('totalNetoAPagar')
            self.TotalIvaRg4310_18 = aut.get('totalIvaRg4310_18')
            self.TotalPagoSegunCondicion = aut.get('totalPagoSegunCondicion')
            self.COE = str(aut.get('coe', ''))
            self.COEAjustado = aut.get('coeAjustado')
            self.Estado = aut.get('estado', '')
            self.NroContrato = aut.get('numeroContrato', '')

            # actualizo parámetros de salida:
            self.params_out['coe'] = self.COE
            self.params_out['coe_ajustado'] = self.COEAjustado
            self.params_out['estado'] = self.Estado
            self.params_out['total_deduccion'] = self.TotalDeduccion
            self.params_out['total_retencion'] = self.TotalRetencion
            self.params_out['total_retencion_afip'] = self.TotalRetencionAfip
            self.params_out['total_otras_retenciones'] = self.TotalOtrasRetenciones
            self.params_out['total_neto_a_pagar'] = self.TotalNetoAPagar
            self.params_out['total_iva_rg_4310_18'] = self.TotalIvaRg4310_18
            self.params_out['total_pago_segun_condicion'] = self.TotalPagoSegunCondicion

            # datos adicionales:
            self.NroOrden = self.params_out['nro_orden'] = aut.get('nroOrden')
            self.params_out['cod_tipo_ajuste'] = aut.get('codTipoAjuste')
            fecha = aut.get('fechaLiquidacion')
            if fecha:
                fecha = str(fecha)
            self.params_out['fecha_liquidacion'] = fecha
            self.params_out['importe_iva'] = aut.get('importeIva')
            self.params_out['nro_op_comercial'] = aut.get('nroOpComercial')
            self.params_out['operacion_con_iva'] = aut.get('operacionConIva')
            self.params_out['precio_operacion'] = aut.get('precioOperacion')
            self.params_out['total_peso_neto'] = aut.get('totalPesoNeto')
            self.params_out['subtotal'] = aut.get('subTotal')
            # LSG (especificos):
            self.params_out['total_deducciones'] = aut.get('totalDeducciones')
            if 'todalPercepciones' in aut:
                # error de tipeo en el WSDL de AFIP...
                self.params_out['total_percepciones'] = aut.get('todalPercepciones')
            else:
                self.params_out['total_percepciones'] = aut.get('totalPercepciones')
            # sub estructuras:
            self.params_out['retenciones'] = []
            self.params_out['deducciones'] = []
            self.params_out['percepciones'] = []
            for retret in aut.get("retenciones", []):
                retret = retret['retencionReturn']
                self.params_out['retenciones'].append({
                    'importe_retencion': retret['importeRetencion'],
                    'alicuota': retret['retencion'].get('alicuota'),
                    'base_calculo': retret['retencion'].get('baseCalculo'),
                    'codigo_concepto': retret['retencion'].get('codigoConcepto'),
                    'detalle_aclaratorio': (retret['retencion'].get('detalleAclaratorio') or "").replace("\n", ""),
                    'importe_certificado_retencion': retret['retencion'].get('importeCertificadoRetencion'),
                    'nro_certificado_retencion': retret['retencion'].get('nroCertificadoRetencion'),
                    'fecha_certificado_retencion': retret['retencion'].get('fechaCertificadoRetencion'),
                    })
            for dedret in aut.get("deducciones", []):
                dedret = dedret['deduccionReturn']
                self.params_out['deducciones'].append({
                    'importe_deduccion': dedret['importeDeduccion'],
                    'importe_iva': dedret.get('importeIva'),
                     'alicuota': dedret['deduccion'].get('alicuotaIva'),
                     'base_calculo': dedret['deduccion'].get('baseCalculo'),
                     'codigo_concepto': dedret['deduccion'].get('codigoConcepto'),
                     'detalle_aclaratorio': dedret['deduccion'].get('detalleAclaratorio', "").replace("\n", ""),
                     'dias_almacenaje': dedret['deduccion'].get('diasAlmacenaje'),
                     'precio_pkg_diario': dedret['deduccion'].get('precioPKGdiario'),
                     'comision_gastos_adm': dedret['deduccion'].get('comisionGastosAdm'),
                    })
            for perret in aut.get("percepciones", []):
                perret = perret.get('percepcionReturn', perret)
                self.params_out['percepciones'].append({
                     'importe_final': perret['percepcion']['importeFinal'],
                     'alicuota': perret['percepcion'].get('alicuota'),
                     'base_calculo': perret['percepcion'].get('baseCalculo'),
                     'descripcion': perret['percepcion'].get('descripcion', "").replace("\n", ""),
                    })
756167
def ConsultarTipoRetencion(self, sep="||"):
        ""
        ret = self.client.tipoRetencionConsultar(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuit': self.Cuit, },
                            )['tipoRetencionReturn']
        self.__analizar_errores(ret)
        array = ret.get('tiposRetencion', [])
        return [("%s %%s %s %%s %s" % (sep, sep, sep)) %
                    (it['codigoDescripcion']['codigo'], 
                     it['codigoDescripcion']['descripcion']) 
               for it in array]
305919
def ConsultarGruposCarne(self, sep="||"):
        ""
        ret = self.client.consultarGruposCarne(
                            authRequest={
                                'token': self.Token, 'sign': self.Sign,
                                'cuitRepresentada': self.Cuit, },
                                )['consultarGruposCarneReturn']
        self.__analizar_errores(ret)
        array = ret.get('arrayGruposCarne', [])
        lista = [it['codigoDescripcionString'] for it in array]
        return [(u"%s {codigo} %s {descripcion} %s" % (sep, sep, sep)).format(**it) if sep else it for it in lista]
423034
def AgregarItemDetalle(self, cuit_cliente, cod_categoria, tipo_liquidacion,
                           cantidad, precio_unitario, alicuota_iva, cod_raza,
                           cantidad_cabezas=None, nro_tropa=None, 
                           cod_corte=None, cantidad_kg_vivo=None,
                           precio_recupero=None, detalle_raza=None,
                           nro_item=None,
                           **kwargs):
        ""
        d = {'cuitCliente': cuit_cliente,
             'codCategoria': cod_categoria,
             'tipoLiquidacion': tipo_liquidacion, 
             'cantidad': cantidad,
             'precioUnitario': precio_unitario, 
             'alicuotaIVA': alicuota_iva, 
             'cantidadCabezas': cantidad_cabezas, 
             'raza': {'codRaza': cod_raza, 'detalle': detalle_raza}, 
             'nroTropa': nro_tropa, 
             'codCorte': cod_corte, 
             'cantidadKgVivo': cantidad_kg_vivo, 
             'precioRecupero': precio_recupero,
             'liquidacionCompraAsociada': [],
             'nroItem': nro_item,
            }
        self.solicitud['itemDetalleLiquidacion'].append(d)
        return True
236875
def ConsultarUltimoRemitoEmitido(self, tipo_comprobante=995, punto_emision=1):
        ""
        response = self.client.consultarUltimoRemitoEmitido(
                                authRequest={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit},
                                tipoComprobante=tipo_comprobante,
                                puntoEmision=punto_emision)
        ret = response.get("consultarUltimoRemitoReturn", {})
        id_req = ret.get("idReq", 0)
        rec = ret.get("remito", {})
        self.__analizar_errores(ret)
        self.__analizar_observaciones(ret)
        self.__analizar_evento(ret)
        self.AnalizarRemito(rec)
        return id_req
758562
def GenerarRemito(self, id_req, archivo="qr.png"):
        ""
        if not self.remito['arrayContingencias']:
            del self.remito['arrayContingencias']
        response = self.client.generarRemito(
                                authRequest={'token': self.Token, 'sign': self.Sign, 'cuitRepresentada': self.Cuit},
                                idReq=id_req, remito=self.remito) 
        ret = response.get("generarRemitoReturn")
        if ret:
            self.__analizar_errores(ret)
            self.__analizar_observaciones(ret)
            self.__analizar_evento(ret)
            self.AnalizarRemito(ret, archivo)
        return bool(self.CodRemito)
1252671
def ConsultarConstanciaCTGPDF(self, numero_ctg=None, 
                                        archivo="constancia.pdf"):
        ""
        ret = self.client.consultarConstanciaCTGPDF(request=dict(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuitRepresentado': self.Cuit, },
                        ctg=numero_ctg, 
                        ))['response']
        self.__analizar_errores(ret)
        datos = base64.b64decode(ret.get('archivo', ""))
        f = open(archivo, "wb")
        f.write(datos)
        f.close()
        return True
881686
def ConsultarDepositosAcopio(self, sep="||"):
        ""
        ret = self.client.consultarDepositosAcopio(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuit': self.Cuit, },
                            )['respuesta']
        self.__analizar_errores(ret)
        array = ret.get('acopio', [])
        if sep is None:
            return array
        else:
            return [("%s %%s %s %%s %s %%s %s %%s %s" % (sep, sep, sep, sep, sep)) %
                    (it['codigo'], it['direccion'], it['localidad'], it['codigoPostal']) 
                    for it in array]
817039
def AjustarLiquidacionUnificado(self):
        ""
        
        # limpiar estructuras no utilizadas (si no hay deducciones / retenciones)
        for k in ('ajusteDebito', 'ajusteCredito'):
            if not any(self.ajuste[k].values()):
                del self.ajuste[k]
            else:
                if not self.ajuste[k]['deducciones']:
                    del self.ajuste[k]['deducciones']
                if not self.ajuste[k]['retenciones']:
                    del self.ajuste[k]['retenciones']

        # llamar al webservice:
        ret = self.client.liquidacionAjustarUnificado(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuit': self.Cuit, },
                        **self.ajuste
                        )
        # analizar el resultado:
        ret = ret['ajusteUnifReturn']
        self.__analizar_errores(ret)
        if 'ajusteUnificado' in ret:
            aut = ret['ajusteUnificado']
            self.AnalizarAjuste(aut)
        return True
952075
def ConsultarPuerto(self, sep="||"):
        ""
        ret = self.client.puertoConsultar(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuit': self.Cuit, },
                            )['puertoReturn']
        self.__analizar_errores(ret)
        array = ret.get('puertos', [])
        return [("%s %%s %s %%s %s" % (sep, sep, sep)) %
                    (it['codigoDescripcion']['codigo'], 
                     it['codigoDescripcion']['descripcion']) 
               for it in array]
502009
def ConsultarAjuste(self, pto_emision=None, nro_orden=None, nro_contrato=None,
                              coe=None, pdf=None):
        ""
        if nro_contrato:
            ret = self.client.ajustePorContratoConsultar(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuit': self.Cuit, },
                        nroContrato=nro_contrato,
                        )
            ret = ret['ajusteContratoReturn']
        elif coe is None or pdf is None:
            ret = self.client.ajusteXNroOrdenConsultar(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuit': self.Cuit, },
                        ptoEmision=pto_emision,
                        nroOrden=nro_orden,
                        pdf='S' if pdf else 'N',
                        )
            ret = ret['ajusteXNroOrdenConsReturn']
        else:
            ret = self.client.ajusteXCoeConsultar(
                       auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuit': self.Cuit, },
                        coe=coe,
                        pdf='S' if pdf else 'N',
                        )
            ret = ret['ajusteConsReturn']

        self.__analizar_errores(ret)
        if 'ajusteUnificado' in ret:
            aut = ret['ajusteUnificado']
            self.AnalizarAjuste(aut)
        # guardo el PDF si se indico archivo y vino en la respuesta:
        if pdf and 'pdf' in ret:
            open(pdf, "wb").write(ret['pdf'])
        return True
464067
def AgregarOtroImpuesto(self, tipo, base_imponible, alicuota, detalle=None):
        ""
        trib = dict(tipo=tipo, baseImponible=base_imponible, alicuota=alicuota,
                    detalle=detalle)
        self.solicitud['otroImpuesto'].append(trib)
        return True