El Destino puede rechazar el CTG a través de la siguiente operatoria
163095
def RechazarCTG(self, carta_porte, ctg, motivo):
        ""
        response = self.client.rechazarCTG(request=dict(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuitRepresentado': self.Cuit, },
                        datosRechazarCTG={
                            'cartaPorte': carta_porte,
                            'ctg': ctg, 'motivoRechazo': motivo,
                            }))['response']
        datos = response.get('datosResponse')
        self.__analizar_errores(response)
        if datos:
            self.CartaPorte = str(datos['cartaPorte'])
            self.NumeroCTG = str(datos['CTG'])
            self.FechaHora = str(datos['fechaHora'])
            self.CodigoOperacion = str(datos['codigoOperacion'])
1353652
public function agregarRuta($metodo, $ruta, $accion, array $parametros = null, $estado_http = 200)
    {
        // Normalizamos el uri de la ruta argumentada
        $ruta = $this->normalizarUri($ruta);

        // Limpiamos y dividimos la ruta en partes
        $partes = explode('/', trim($ruta, '/ '));

        // Contamos las partes resultantes
        $conteo_partes = count($partes);

        // Declaramos la rama base como actual
        $rama_actual = &$this->arbol_rutas;

        // Preparamos variable que clasifica la ruta como simple
        $es_simple = true;

        // Verificamos si hay suficientes partes para recorrerlas
        if (!($conteo_partes === 1 && $partes[0] === '')) {

            // Recorremos las partes para actualizar la rama actual
            for ($i = 0; $i < $conteo_partes; $i++) {

                if (substr($partes[$i], 0, 1) == ':') {
                    $es_simple = false;
                    if (!isset($rama_actual['ramas']['*'])) {
                        $rama_actual['ramas']['*'] = ['ramas' => [], 'nombre' => substr($partes[$i], 1)];
                    }

                    $rama_actual = &$rama_actual['ramas']['*'];
                } else {
                    if (!isset($rama_actual['ramas'][$partes[$i]])) {
                        $rama_actual['ramas'][$partes[$i]] = ['ramas' => []];
                    }

                    $rama_actual = &$rama_actual['ramas'][$partes[$i]];
                }
            }

        }

        // Preparamos el metodo argumentado
        $metodo = (array)$metodo;

        // Insertamos la ruta a la rama actual
        $rama_actual['ruta'] = $ruta;

        // Preparamos las acciones de la rama actual
        if (!isset($rama_actual['x'])) {
            $rama_actual['x'] = [];
        }

        // Recorremos los metodos para agregar las respectivas acciones
        foreach ($metodo as $m) {
            // Agregamos ruta simple en caso necesario
            if ($es_simple) {
                $this->rutas_simples[$ruta][strtoupper($m)]['accion'] = $accion;
                $this->rutas_simples[$ruta][strtoupper($m)]['estado_http'] = $estado_http;
                if (isset($parametros)) {
                    $this->rutas_simples[$ruta][strtoupper($m)]['parametros'] = $parametros;
                }
            } else {
                $rama_actual['x'][strtoupper($m)]['accion'] = $accion;
                $rama_actual['x'][strtoupper($m)]['estado_http'] = $estado_http;
                if (isset($parametros)) {
                    $rama_actual['x'][strtoupper($m)]['parametros'] = $parametros;
                }
            }
        }

        // Liberamos memoria
        unset($rama_actual);
    }
832665
def ConsultarRetencionesTabacaleras(self, sep="||"):
        ""
        ret = self.client.consultarRetencionesTabacaleras(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuit': self.Cuit, },
                            )['respuesta']
        self.__analizar_errores(ret)
        array = ret.get('retencion', [])
        if sep is None:
            return dict([(it['codigo'], it['descripcion']) for it in array])
        else:
            return [("%s %%s %s %%s %s" % (sep, sep, sep)) %
                    (it['codigo'], it['descripcion']) for it in array]
1318457
def ConsultarCTGExcel(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,
                     archivo="planilla.xls"):
        ""
        ret = self.client.consultarCTGExcel(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 = base64.b64decode(ret.get('archivo') or "")
        f = open(archivo, "wb")
        f.write(datos)
        f.close()
        return True
678572
public function generar()
    {
        // si ya se había generado se entrega directamente
        if ($this->xml_data)
            return $this->xml_data;
        // si no hay DTEs para generar entregar falso
        if (!isset($this->dtes[0])) {
            \sasco\LibreDTE\Log::write(
                \sasco\LibreDTE\Estado::ENVIODTE_FALTA_DTE,
                \sasco\LibreDTE\Estado::get(\sasco\LibreDTE\Estado::ENVIODTE_FALTA_DTE)
            );
            return false;
        }
        // genear XML del envío
        $xmlEnvio = (new \sasco\LibreDTE\XML())->generate([
            $this->config['tipos'][$this->tipo] => [
                '@attributes' => [
                    'xmlns' => 'http://www.sii.cl/SiiDte',
                    'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                    'xsi:schemaLocation' => 'http://www.sii.cl/SiiDte '.$this->config['schemas'][$this->tipo].'.xsd',
                    'version' => '1.0'
                ],
                'SetDTE' => [
                    '@attributes' => [
                        'ID' => 'LibreDTE_SetDoc'
                    ],
                    'Caratula' => $this->caratula,
                    'DTE' => null,
                ]
            ]
        ])->saveXML();
        // generar XML de los DTE que se deberán incorporar
        $DTEs = [];
        foreach ($this->dtes as &$DTE) {
            $DTEs[] = trim(str_replace(['<?xml version="1.0" encoding="ISO-8859-1"?>', '<?xml version="1.0"?>'], '', $DTE->saveXML()));
        }
        // firmar XML del envío y entregar
        $xml = str_replace('<DTE/>', implode("\n", $DTEs), $xmlEnvio);
        $this->xml_data = $this->Firma ? $this->Firma->signXML($xml, '#LibreDTE_SetDoc', 'SetDTE', true) : $xml;
        return $this->xml_data;
    }
1367469
public function doTic()
    {
        $aData = &$this->aData;
        $fNow = microtime(true);

        if ($fNow >= $aData['lap_end'] || $this->isTimeLimitExceeded()) {
            $iNbEventsPerSec = round($aData['lap_nb_events'] / ($fNow - $aData['lap_start']));
            $sMsg = sprintf(
                $this->sFormat,
                $iNbEventsPerSec,
                $aData['lap_nb_events'],
                $aData['total_nb_events']
            );
            $aData['lap_start'] = $fNow;
            $aData['lap_end'] += $aData['lap_duration'] * ceil(($fNow - $aData['lap_end']) / $aData['lap_duration']);
            $aData['lap_nb_events'] = 0;
        } else {
            $sMsg = '';
        }

        return $sMsg;
    }
781705
def Guardar(self, tipo_doc, nro_doc, denominacion, cat_iva, direccion, 
               email, imp_ganancias='NI', imp_iva='NI', monotributo='NI', 
               integrante_soc='N', empleador='N'):
        ""
        if self.Buscar(nro_doc, tipo_doc):
            sql = ("UPDATE padron SET denominacion=?, cat_iva=?, email=?, "
					"imp_ganancias=?, imp_iva=?, monotributo=?, "
					"integrante_soc=?, empleador=? "
                    "WHERE tipo_doc=? AND nro_doc=?")
            params = [denominacion, cat_iva, email, imp_ganancias, 
                      imp_iva, monotributo, integrante_soc, empleador,
                     tipo_doc, nro_doc]
        else:
            sql = ("INSERT INTO padron (tipo_doc, nro_doc, denominacion, "
                    "cat_iva, email, imp_ganancias, imp_iva, monotributo, "
                    "integrante_soc, empleador) "
                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
            params = [tipo_doc, nro_doc, denominacion, cat_iva, email,
                      imp_ganancias, imp_iva, monotributo, 
                      integrante_soc, empleador]
        self.cursor.execute(sql, params)
        # agregar el domicilio solo si no existe:
        if direccion:
            self.cursor.execute("SELECT * FROM domicilio WHERE direccion=? "
                                "AND tipo_doc=? AND nro_doc=?", 
                                [direccion, tipo_doc, nro_doc])
            if self.cursor.rowcount < 0:
                sql = ("INSERT INTO domicilio (nro_doc, tipo_doc, direccion)"
                        "VALUES (?, ?, ?)")
                self.cursor.execute(sql, [nro_doc, tipo_doc, direccion])
        self.db.commit()
        return True
1241153
def verifica(ver_list, res_dict, difs):
    ""
    for k, v in ver_list.items():
        # normalizo a float para poder comparar numericamente:
        if isinstance(v, (Decimal, int, long)):
            v = float(v)
        if isinstance(res_dict.get(k), (Decimal, int, long)):
            res_dict[k] = float(res_dict[k])
        if isinstance(v, list):
            # verifico que ambas listas tengan la misma cantidad de elementos:
            if v and not k in res_dict and v:
                difs.append("falta tag %s: %s %s" % (k, repr(v), repr(res_dict.get(k))))
            elif len(res_dict.get(k, []))!=len(v or []):
                difs.append("tag %s len !=: %s %s" % (k, repr(v), repr(res_dict.get(k))))
            else:
                # ordeno las listas para poder compararlas si vienen mezcladas
                rl = sorted(res_dict.get(k, []))
                # comparo los elementos uno a uno:
                for i, vl in enumerate(sorted(v)):
                    verifica(vl, rl[i], difs)
        elif isinstance(v, dict):
            # comparo recursivamente los elementos:
            verifica(v, res_dict.get(k, {}), difs)
        elif res_dict.get(k) is None or v is None:
            # alguno de los dos es nulo, verifico si ambos lo son o faltan
            if v=="":
                v = None
            r = res_dict.get(k)
            if r=="":
                r = None
            if not (r is None and v is None):
                difs.append("%s: nil %s!=%s" % (k, repr(v), repr(r)))
        elif type(res_dict.get(k)) == type(v):
            # tipos iguales, los comparo directamente
            if res_dict.get(k) != v:
                difs.append("%s: %s!=%s" % (k, repr(v), repr(res_dict.get(k))))
        elif isinstance(v, float) or isinstance(res_dict.get(k), float):
            # comparar numericamente
            if float(res_dict.get(k)) != float(v):
                difs.append("%s: %s!=%s" % (k, repr(v), repr(res_dict.get(k))))
        elif unicode(res_dict.get(k)) != unicode(v):
            # tipos diferentes, comparo la representación  
            difs.append("%s: str %s!=%s" % (k, repr(v), repr(res_dict.get(k))))
        else:
            pass
205571
public static function gerar()
    {
        $cnpj = array ();
        for ($i = 0; $i < 8; $i++) {
            $cnpj[$i] = rand(0, 9);
        }
        $cnpj[8]  = 0;
        $cnpj[9]  = 0;
        $cnpj[10] = 0;
        $cnpj[11] = 1;

        // Primeiro dígito
        $multiplicadores = array (5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2);
        $soma            = 0;
        for ($i = 0; $i <= 11; $i++) {
            $soma += $multiplicadores[$i] * $cnpj[$i];
        }
        $d1 = 11 - ($soma % 11);
        if ($d1 >= 10) {
            $d1 = 0;
        }
        $cnpj[12] = $d1;

        // Segundo dígito
        $multiplicadores = array (6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2);
        $soma            = 0;
        for ($i = 0; $i <= 12; $i++) {
            $soma += $multiplicadores[$i] * $cnpj[$i];
        }
        $d2 = 11 - ($soma % 11);
        if ($d2 >= 10) {
            $d2 = 0;
        }
        $cnpj[13] = $d2;

        return static::formatar(implode("", $cnpj));
    }
1204883
def AgregarCTG(self, nro_ctg=None, nro_carta_porte=None,
                         porcentaje_secado_humedad=None, importe_secado=None,
                         peso_neto_merma_secado=None, tarifa_secado=None,
                         importe_zarandeo=None, peso_neto_merma_zarandeo=None,
                         tarifa_zarandeo=None, 
                         peso_neto_confirmado_definitivo=None,
                         **kwargs):
        ""
        
        ctg = dict(
                nroCTG=nro_ctg,
                nroCartaDePorte=nro_carta_porte,
                pesoNetoConfirmadoDefinitivo=peso_neto_confirmado_definitivo,
                porcentajeSecadoHumedad=porcentaje_secado_humedad,
                importeSecado=importe_secado,
                pesoNetoMermaSecado=peso_neto_merma_secado,
                tarifaSecado=tarifa_secado,
                importeZarandeo=importe_zarandeo,
                pesoNetoMermaZarandeo=peso_neto_merma_zarandeo,
                tarifaZarandeo=tarifa_zarandeo,
            )
        self.certificacion['primaria']['ctg'].append(ctg)
        return True
530586
private static function _configureLogger()
    {
        //brak konfiguracji
        if (!self::$_config) {
            //tworzy pustą konfigurację
            return new \Psr\Log\NullLogger;
        }
        //nowy obiekt loggera
        $logger = new Logger(self::$_config->getName());
        //iteracja po konfiguracjach instancji
        foreach (self::$_config as $config) {
            self::_configureInstance($config, $logger);
        }
        return $logger;
    }
387311
public function main()
    {
        // cargar XML y extraer arreglo con datos de carátula y DTEs
        $EnvioDte = new \sasco\LibreDTE\Sii\EnvioDte();
        $EnvioDte->loadXML(file_get_contents($this->args['xml']));
        $Caratula = $EnvioDte->getCaratula();
        $Documentos = $EnvioDte->getDocumentos();
        // procesar cada DTEs e ir creando los archivos PDF
        foreach ($Documentos as $DTE) {
            if (!$DTE->getDatos())
                $this->error('No se pudieron obtener los datos de uno de los DTE del XML');
            $this->out('Generando PDF para DTE '.$DTE->getID());
            $pdf = new \sasco\LibreDTE\Sii\Dte\PDF\Dte($this->args['papel']);
            $pdf->setFooterText();
            if ($this->args['logo'])
                $pdf->setLogo($this->args['logo']);
            $pdf->setResolucion(['FchResol'=>$Caratula['FchResol'], 'NroResol'=>$Caratula['NroResol']]);
            $pdf->setWebVerificacion($this->args['web']);
            $pdf->agregar($DTE->getDatos(), $DTE->getTED());
            if (isset($this->args['cedible'])) {
                $pdf->setCedible(true);
                $pdf->agregar($DTE->getDatos(), $DTE->getTED());
            }
            $pdf->Output($this->args['dir'].'/dte_'.$Caratula['RutEmisor'].'_'.$DTE->getID().'.pdf', 'F');
        }
        return 0;
    }
790097
def AjustarLiquidacionContrato(self):
        ""
        
        # limpiar arrays no enviados:
        if not self.ajuste['ajusteBase']['certificados']:
            del self.ajuste['ajusteBase']['certificados']
        for k1 in ('ajusteCredito', 'ajusteDebito'):
            for k2 in ('retenciones', 'deducciones'):
                if not self.ajuste[k1][k2]:
                    del self.ajuste[k1][k2]

        ret = self.client.liquidacionAjustarContrato(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuit': self.Cuit, },
                        **self.ajuste
                        )
        ret = ret['ajusteContratoReturn']
        self.__analizar_errores(ret)
        if 'ajusteContrato' in ret:
            aut = ret['ajusteContrato']
            self.AnalizarAjuste(aut)
        return True
75837
def AgregarEmisor(self, tipo_cbte, pto_vta, nro_cbte, cod_caracter=None,
                      fecha_inicio_act=None, iibb=None, nro_ruca=None,
                      nro_renspa=None, cuit_autorizado=None, **kwargs):
        ""
        # cod_caracter y fecha_inicio_act no es requerido para ajustes
        d = {'tipoComprobante': tipo_cbte, 'puntoVenta': pto_vta,
             'nroComprobante': nro_cbte, 
             'codCaracter': cod_caracter,
             'fechaInicioActividades': fecha_inicio_act,
             'iibb': iibb,
             'nroRUCA': nro_ruca,
             'nroRenspa': nro_renspa,
             'cuitAutorizado': cuit_autorizado}
        self.solicitud['emisor'].update(d)
        return True
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
1330418
def AnularCTG(self, carta_porte, ctg):
        ""
        response = self.client.anularCTG(request=dict(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuitRepresentado': self.Cuit, },
                        datosAnularCTG={
                            'cartaPorte': carta_porte,
                            'ctg': ctg, }))['response']
        datos = response.get('datosResponse')
        self.__analizar_errores(response)
        if datos:
            self.CartaPorte = str(datos['cartaPorte'])
            self.NumeroCTG = str(datos['ctg'])
            self.FechaHora = str(datos['fechaHora'])
            self.CodigoOperacion = str(datos['codigoOperacion'])
689118
def CambiarDestinoDestinatarioCTGRechazado(self, numero_carta_de_porte, 
                            numero_ctg, codigo_localidad_destino=None,
                            cuit_destino=None, cuit_destinatario=None,
                            km_a_recorrer=None, turno=None,
                            **kwargs):
        ""
        ret = self.client.cambiarDestinoDestinatarioCTGRechazado(request=dict(
                        auth={
                            'token': self.Token, 'sign': self.Sign,
                            'cuitRepresentado': self.Cuit, },
                        datosCambiarDestinoDestinatarioCTGRechazado=dict(
                            cartaPorte=numero_carta_de_porte,
                            ctg=numero_ctg, 
                            codigoLocalidadDestino=codigo_localidad_destino,
                            cuitDestino=cuit_destino, 
                            cuitDestinatario=cuit_destinatario,
                            kmARecorrer=km_a_recorrer,
                            turno=turno,
                            )))['response']
        self.__analizar_errores(ret)
        datos = ret.get('datosResponse')
        if datos:
            self.CartaPorte = str(datos['cartaPorte'])
            self.NumeroCTG = str(datos['ctg'])
            self.FechaHora = str(datos['fechaHora'])
            self.CodigoTransaccion = str(datos['codigoOperacion'])
            self.Observaciones = ""
        return self.CodigoTransaccion