* * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-16 */ // respuesta en texto plano header('Content-type: text/plain; charset=ISO-8859-1'); // incluir archivos php de la biblioteca y configuraciones include 'inc.php'; // caratula del libro $caratula = ['RutEmisorLibro' => '76192083-9', 'RutEnvia' => '11222333-4', 'PeriodoTributario' => '1980-03', 'FchResol' => '2006-01-20', 'NroResol' => 102006, 'TipoOperacion' => 'VENTA', 'TipoLibro' => 'ESPECIAL', 'TipoEnvio' => 'TOTAL', 'FolioNotificacion' => 102006]; // datos del emisor $Emisor = ['RUTEmisor' => '76192083-9', 'RznSoc' => 'SASCO SpA', 'GiroEmis' => 'Servicios integrales de informática', 'Acteco' => 726000, 'DirOrigen' => 'Santiago', 'CmnaOrigen' => 'Santiago']; // datos de los DTE (cada elemento del arreglo $set_pruebas es un DTE) // IMPORTANTE: folios deben coincidir con los de los DTEs que fueron aceptados // en el proceso de certificación del set de pruebas básico $set_pruebas = [['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => 21], 'Emisor' => $Emisor, 'Receptor' => ['RUTRecep' => '55666777-8', 'RznSocRecep' => 'Empresa S.A.', 'GiroRecep' => 'Servicios jurídicos', 'DirRecep' => 'Santiago', 'CmnaRecep' => 'Santiago']], 'Detalle' => [['NmbItem' => 'Cajón AFECTO', 'QtyItem' => 123, 'PrcItem' => 923], ['NmbItem' => 'Relleno AFECTO', 'QtyItem' => 53, 'PrcItem' => 1473]], 'Referencia' => ['TpoDocRef' => 'SET', 'FolioRef' => 21, 'RazonRef' => 'CASO 414175-1']], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => 22], 'Emisor' => $Emisor, 'Receptor' => ['RUTRecep' => '55666777-8', 'RznSocRecep' => 'Empresa S.A.', 'GiroRecep' => 'Servicios jurídicos', 'DirRecep' => 'Santiago', 'CmnaRecep' => 'Santiago']], 'Detalle' => [['NmbItem' => 'Pañuelo AFECTO', 'QtyItem' => 235, 'PrcItem' => 1926, 'DescuentoPct' => 4], ['NmbItem' => 'ITEM 2 AFECTO', 'QtyItem' => 161, 'PrcItem' => 990, 'DescuentoPct' => 5]], 'Referencia' => ['TpoDocRef' => 'SET', 'FolioRef' => 22, 'RazonRef' => 'CASO 414175-2']], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => 23], 'Emisor' => $Emisor, 'Receptor' => ['RUTRecep' => '55666777-8', 'RznSocRecep' => 'Empresa S.A.', 'GiroRecep' => 'Servicios jurídicos', 'DirRecep' => 'Santiago', 'CmnaRecep' => 'Santiago']], 'Detalle' => [['NmbItem' => 'Pintura B&W AFECTO', 'QtyItem' => 24, 'PrcItem' => 1937], ['NmbItem' => 'ITEM 2 AFECTO', 'QtyItem' => 149, 'PrcItem' => 2975], ['IndExe' => 1, 'NmbItem' => 'ITEM 3 SERVICIO EXENTO', 'QtyItem' => 1, 'PrcItem' => 34705]], 'Referencia' => ['TpoDocRef' => 'SET', 'FolioRef' => 23, 'RazonRef' => 'CASO 414175-3']], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => 24], 'Emisor' => $Emisor, 'Receptor' => ['RUTRecep' => '55666777-8', 'RznSocRecep' => 'Empresa S.A.', 'GiroRecep' => 'Servicios jurídicos', 'DirRecep' => 'Santiago', 'CmnaRecep' => 'Santiago']], 'Detalle' => [['NmbItem' => 'ITEM 1 AFECTO', 'QtyItem' => 81, 'PrcItem' => 1672], ['NmbItem' => 'ITEM 2 AFECTO', 'QtyItem' => 35, 'PrcItem' => 1405], ['IndExe' => 1, 'NmbItem' => 'ITEM 3 SERVICIO EXENTO', 'QtyItem' => 2, 'PrcItem' => 6767]], 'DscRcgGlobal' => ['TpoMov' => 'D', 'TpoValor' => '%', 'ValorDR' => 6], 'Referencia' => ['TpoDocRef' => 'SET', 'FolioRef' => 24, 'RazonRef' => 'CASO 414175-4']], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 61, 'Folio' => 13], 'Emisor' => $Emisor, 'Receptor' => ['RUTRecep' => '55666777-8', 'RznSocRecep' => 'Empresa S.A.', 'GiroRecep' => 'Servicios jurídicos', 'DirRecep' => 'Santiago', 'CmnaRecep' => 'Santiago'], 'Totales' => ['MntTotal' => 0]], 'Detalle' => [['NmbItem' => 'Cajón AFECTO']], 'Referencia' => [['TpoDocRef' => 'SET', 'FolioRef' => 13, 'RazonRef' => 'CASO 414175-5'], ['TpoDocRef' => 33, 'FolioRef' => 21, 'CodRef' => 2, 'RazonRef' => 'CORRIGE GIRO DEL RECEPTOR']]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 61, 'Folio' => 14], 'Emisor' => $Emisor, 'Receptor' => ['RUTRecep' => '55666777-8', 'RznSocRecep' => 'Empresa S.A.', 'GiroRecep' => 'Servicios jurídicos', 'DirRecep' => 'Santiago', 'CmnaRecep' => 'Santiago'], 'Totales' => ['MntNeto' => 0, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]], 'Detalle' => [['NmbItem' => 'Pañuelo AFECTO', 'QtyItem' => 86, 'PrcItem' => 1926, 'DescuentoPct' => 4], ['NmbItem' => 'ITEM 2 AFECTO', 'QtyItem' => 109, 'PrcItem' => 990, 'DescuentoPct' => 5]], 'Referencia' => [['TpoDocRef' => 'SET', 'FolioRef' => 14, 'RazonRef' => 'CASO 414175-6'], ['TpoDocRef' => 33, 'FolioRef' => 22, 'CodRef' => 3, 'RazonRef' => 'DEVOLUCION DE MERCADERIAS']]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 61, 'Folio' => 15], 'Emisor' => $Emisor, 'Receptor' => ['RUTRecep' => '55666777-8', 'RznSocRecep' => 'Empresa S.A.', 'GiroRecep' => 'Servicios jurídicos', 'DirRecep' => 'Santiago', 'CmnaRecep' => 'Santiago'], 'Totales' => ['MntNeto' => 0, 'MntExe' => 0, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]], 'Detalle' => [['NmbItem' => 'Pintura B&W AFECTO', 'QtyItem' => 24, 'PrcItem' => 1937], ['NmbItem' => 'ITEM 2 AFECTO', 'QtyItem' => 149, 'PrcItem' => 2975], ['IndExe' => 1, 'NmbItem' => 'ITEM 3 SERVICIO EXENTO', 'QtyItem' => 1, 'PrcItem' => 34705]], 'Referencia' => [['TpoDocRef' => 'SET', 'FolioRef' => 15, 'RazonRef' => 'CASO 414175-7'], ['TpoDocRef' => 33, 'FolioRef' => 23, 'CodRef' => 1, 'RazonRef' => 'ANULA FACTURA']]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 56, 'Folio' => 5], 'Emisor' => $Emisor, 'Receptor' => ['RUTRecep' => '55666777-8', 'RznSocRecep' => 'Empresa S.A.', 'GiroRecep' => 'Servicios jurídicos', 'DirRecep' => 'Santiago', 'CmnaRecep' => 'Santiago'], 'Totales' => ['MntTotal' => 0]], 'Detalle' => [['NmbItem' => 'Cajón AFECTO']], 'Referencia' => [['TpoDocRef' => 'SET', 'FolioRef' => 5, 'RazonRef' => 'CASO 414175-8'], ['TpoDocRef' => 61, 'FolioRef' => 13, 'CodRef' => 1, 'RazonRef' => 'ANULA NOTA DE CREDITO ELECTRONICA']]]]; // Objetos de Firma y LibroCompraVenta $Firma = new \sasco\LibreDTE\FirmaElectronica($config['firma']); $LibroCompraVenta = new \sasco\LibreDTE\Sii\LibroCompraVenta(); // generar cada DTE y agregar su resumen al detalle del libro foreach ($set_pruebas as $documento) { $DTE = new \sasco\LibreDTE\Sii\Dte($documento); $LibroCompraVenta->agregar($DTE->getResumen(), false); // agregar detalle sin normalizar } // enviar libro de ventas y mostrar resultado del envío: track id o bien =false si hubo error $LibroCompraVenta->setCaratula($caratula); $LibroCompraVenta->generar(false); // generar XML sin firma y sin detalle $LibroCompraVenta->setFirma($Firma); $track_id = $LibroCompraVenta->enviar();
/** * Método que normaliza los datos de una factura electrónica * @param datos Arreglo con los datos del documento que se desean normalizar * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-20 */ private function normalizar_33(array &$datos) { // completar con nodos por defecto $datos = \sasco\LibreDTE\Arreglo::mergeRecursiveDistinct(['Encabezado' => ['IdDoc' => false, 'Emisor' => false, 'Receptor' => false, 'Totales' => ['MntNeto' => 0, 'MntExe' => false, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]]], $datos); // normalizar datos $this->normalizar_detalle($datos); $this->normalizar_aplicar_descuentos_recargos($datos, ['MntNeto', 'MntExe']); $this->normalizar_agregar_IVA_MntTotal($datos); }
/** * Método que obtiene los datos para generar los tags TotalesPeriodo * @return Arreglo con los datos para generar los tags TotalesPeriodo * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-14 */ private function getResumenPeriodo() { $resumen = []; foreach ($this->detalles as &$d) { // si el tipo de boleta no está en el resumen se crea if (!isset($resumen[$d['TpoDoc']])) { $resumen[$d['TpoDoc']] = ['TpoDoc' => $d['TpoDoc'], 'TotAnulado' => false, 'TotalesServicio' => []]; } // si no existe el tipo de servicio se agrega if (!isset($resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']])) { $resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']] = ['TpoServ' => $d['TpoServ'], 'PeriodoDevengado' => false, 'TotDoc' => false, 'TotMntExe' => false, 'TotMntNeto' => false, 'TasaIVA' => false, 'TotMntIVA' => false, 'TotMntTotal' => false, 'TotMntNoFact' => false, 'TotMntPeriodo' => false, 'TotSaldoAnt' => false, 'TotVlrPagar' => false, 'TotTicket' => false]; } // agregar detalle al resumen if (empty($d['Anulado'])) { // contabilizar documento $resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']]['TotDoc'] += 1; // ir sumando valores $vals = ['MntExe' => 'TotMntExe', 'MntTotal' => 'TotMntTotal', 'MntNoFact' => 'TotMntNoFact', 'MntPeriodo' => 'TotMntPeriodo', 'SaldoAnt' => 'TotSaldoAnt', 'VlrPagar' => 'TotVlrPagar', 'TotTicketBoleta' => 'TotTicket']; foreach ($vals as $ori => $des) { if ($d[$ori]) { $resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']][$des] += $d[$ori]; } } // determinar neto e iva $tasa = \sasco\LibreDTE\Sii::getIVA(); $neto = round(($d['MntTotal'] - $d['MntExe']) / (1 + $tasa / 100)); if ($neto) { $resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']]['TotMntNeto'] += $neto; $resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']]['TasaIVA'] = $tasa; // WARNING: problema por aproximaciones al calcular el NETO e IVA a partir del BRUTO //$resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']]['TotMntIVA'] = round($resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']]['TotMntNeto'] * ($tasa/100)); $resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']]['TotMntIVA'] = $resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']]['TotMntTotal'] - $resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']]['TotMntExe'] - $resumen[$d['TpoDoc']]['TotalesServicio'][$d['TpoServ']]['TotMntNeto']; } } } // armar resumen verdadero $ResumenPeriodo = ['TotalesPeriodo' => []]; foreach ($resumen as $r) { $ResumenPeriodo['TotalesPeriodo'][] = $r; } // entregar resumen return $ResumenPeriodo; }
* * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-16 */ // respuesta en texto plano header('Content-type: text/plain'); // incluir archivos php de la biblioteca y configuraciones include 'inc.php'; // caratula del libro $caratula = ['RutEmisorLibro' => '76192083-9', 'RutEnvia' => '11222333-4', 'PeriodoTributario' => '2000-03', 'FchResol' => '2006-01-20', 'NroResol' => 102006, 'TipoOperacion' => 'COMPRA', 'TipoLibro' => 'ESPECIAL', 'TipoEnvio' => 'TOTAL', 'FolioNotificacion' => 102006]; // EN FACTURA CON IVA USO COMUN CONSIDERE QUE EL FACTOR DE PROPORCIONALIDAD // DEL IVA ES DE 0.60 $factor_proporcionalidad_iva = 60; // se divide por 100 al agregar al resumen del período // set de pruebas compras - número de atención 414177 $detalles = [['TpoDoc' => 30, 'NroDoc' => 234, 'TasaImp' => \sasco\LibreDTE\Sii::getIVA(), 'FchDoc' => $caratula['PeriodoTributario'] . '-01', 'RUTDoc' => '78885550-8', 'MntNeto' => 53253], ['TpoDoc' => 33, 'NroDoc' => 32, 'TasaImp' => \sasco\LibreDTE\Sii::getIVA(), 'FchDoc' => $caratula['PeriodoTributario'] . '-01', 'RUTDoc' => '78885550-8', 'MntExe' => 10633, 'MntNeto' => 11473], ['TpoDoc' => 30, 'NroDoc' => 781, 'TasaImp' => \sasco\LibreDTE\Sii::getIVA(), 'FchDoc' => $caratula['PeriodoTributario'] . '-02', 'RUTDoc' => '78885550-8', 'MntNeto' => 30171, 'FctProp' => $factor_proporcionalidad_iva], ['TpoDoc' => 60, 'NroDoc' => 451, 'TasaImp' => \sasco\LibreDTE\Sii::getIVA(), 'FchDoc' => $caratula['PeriodoTributario'] . '-03', 'RUTDoc' => '78885550-8', 'MntNeto' => 2928], ['TpoDoc' => 33, 'NroDoc' => 67, 'TasaImp' => \sasco\LibreDTE\Sii::getIVA(), 'FchDoc' => $caratula['PeriodoTributario'] . '-04', 'RUTDoc' => '78885550-8', 'MntNeto' => 12135, 'IVANoRec' => ['CodIVANoRec' => 4, 'MntIVANoRec' => round(12135 * (\sasco\LibreDTE\Sii::getIVA() / 100))]], ['TpoDoc' => 46, 'NroDoc' => 9, 'TasaImp' => \sasco\LibreDTE\Sii::getIVA(), 'FchDoc' => $caratula['PeriodoTributario'] . '-05', 'RUTDoc' => '78885550-8', 'MntNeto' => 10632, 'OtrosImp' => ['CodImp' => 15, 'TasaImp' => \sasco\LibreDTE\Sii::getIVA(), 'MntImp' => round(10632 * (\sasco\LibreDTE\Sii::getIVA() / 100))]], ['TpoDoc' => 60, 'NroDoc' => 211, 'TasaImp' => \sasco\LibreDTE\Sii::getIVA(), 'FchDoc' => $caratula['PeriodoTributario'] . '-06', 'RUTDoc' => '78885550-8', 'MntNeto' => 9053]]; // Objetos de Firma y LibroCompraVenta $Firma = new \sasco\LibreDTE\FirmaElectronica($config['firma']); $LibroCompraVenta = new \sasco\LibreDTE\Sii\LibroCompraVenta(); // agregar cada uno de los detalles al libro foreach ($detalles as $detalle) { $LibroCompraVenta->agregar($detalle); } // enviar libro de compras y mostrar resultado del envío: track id o bien =false si hubo error $LibroCompraVenta->setCaratula($caratula); $LibroCompraVenta->generar(); // generar XML sin firma $LibroCompraVenta->setFirma($Firma); $track_id = $LibroCompraVenta->enviar(); // enviar XML generado en línea anterior var_dump($track_id);
* * Ejemplo que genera y envía el libro electrónico de guías de despachos. * * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-10-02 */ // respuesta en texto plano header('Content-type: text/plain'); // incluir archivos php de la biblioteca y configuraciones include 'inc.php'; // caratula del libro $caratula = ['RutEmisorLibro' => '76192083-9', 'FchResol' => '2014-12-05', 'NroResol' => 0, 'FolioNotificacion' => 1]; // receptor de las guías $receptor = '55666777-8'; // set de pruebas guías - número de atención 414177 $detalles = [['Folio' => 4, 'TpoOper' => 5, 'RUTDoc' => $caratula['RutEmisorLibro'], 'TasaImp' => \sasco\LibreDTE\Sii::getIVA()], ['Folio' => 5, 'TpoOper' => 1, 'RUTDoc' => $receptor, 'MntNeto' => 1375761, 'TasaImp' => \sasco\LibreDTE\Sii::getIVA(), 'TpoDocRef' => 33, 'FolioDocRef' => 69, 'FchDocRef' => date('Y-m-d')], ['Folio' => 6, 'Anulado' => 2, 'TpoOper' => 1, 'RUTDoc' => $receptor, 'MntNeto' => 1050032, 'TasaImp' => \sasco\LibreDTE\Sii::getIVA()]]; // Objetos de Firma y LibroGuia $Firma = new \sasco\LibreDTE\FirmaElectronica($config['firma']); $LibroGuia = new \sasco\LibreDTE\Sii\LibroGuia(); // agregar cada uno de los detalles al libro foreach ($detalles as $detalle) { $LibroGuia->agregar($detalle); } // enviar libro de guías y mostrar resultado del envío: track id o bien =false si hubo error $LibroGuia->setFirma($Firma); $LibroGuia->setCaratula($caratula); $LibroGuia->generar(); $track_id = $LibroGuia->enviar(); // enviar XML generado en línea anterior var_dump($track_id); // si hubo errores mostrar
break; } $EnvioDTE->agregar($DTE); } $EnvioDTE->setFirma($Firma); $EnvioDTE->setCaratula($caratula); $EnvioDTE->generar(); if ($EnvioDTE->schemaValidate()) { if (is_writable('xml/EnvioBOLETA.xml')) { file_put_contents('xml/EnvioBOLETA.xml', $EnvioDTE->generar()); } // guardar XML en sistema de archivos echo $EnvioDTE->generar(); } // crear notas de crédito para el set de prueba $notas_credito = [\sasco\LibreDTE\Arreglo::mergeRecursiveDistinct($set_pruebas[0], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 61, 'Folio' => $folios[61], 'MntBruto' => 1], 'Totales' => ['MntNeto' => 0, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]], 'Referencia' => ['TpoDocRef' => $set_pruebas[0]['Encabezado']['IdDoc']['TipoDTE'], 'FolioRef' => $set_pruebas[0]['Encabezado']['IdDoc']['Folio'], 'CodRef' => 1, 'RazonRef' => 'ANULA BOLETA']]), \sasco\LibreDTE\Arreglo::mergeRecursiveDistinct($set_pruebas[2], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 61, 'Folio' => $folios[61] + 1, 'MntBruto' => 1], 'Totales' => ['MntNeto' => 0, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]], 'Referencia' => ['TpoDocRef' => $set_pruebas[2]['Encabezado']['IdDoc']['TipoDTE'], 'FolioRef' => $set_pruebas[2]['Encabezado']['IdDoc']['Folio'], 'CodRef' => 1, 'RazonRef' => 'ANULA BOLETA']]), \sasco\LibreDTE\Arreglo::mergeRecursiveDistinct($set_pruebas[4], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 61, 'Folio' => $folios[61] + 2, 'MntBruto' => 1], 'Totales' => ['MntNeto' => 0, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]], 'Referencia' => ['TpoDocRef' => $set_pruebas[4]['Encabezado']['IdDoc']['TipoDTE'], 'FolioRef' => $set_pruebas[4]['Encabezado']['IdDoc']['Folio'], 'CodRef' => 1, 'RazonRef' => 'ANULA BOLETA']]), \sasco\LibreDTE\Arreglo::mergeRecursiveDistinct($set_pruebas[6], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 61, 'Folio' => $folios[61] + 3, 'MntBruto' => 1], 'Totales' => ['MntNeto' => 0, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]], 'Detalle' => [['QtyItem' => $set_pruebas[6]['Detalle'][0]['QtyItem'] * 0.4]], 'Referencia' => ['TpoDocRef' => $set_pruebas[6]['Encabezado']['IdDoc']['TipoDTE'], 'FolioRef' => $set_pruebas[6]['Encabezado']['IdDoc']['Folio'], 'CodRef' => 3, 'RazonRef' => 'SE REBAJA EN UN 40%']]), \sasco\LibreDTE\Arreglo::mergeRecursiveDistinct($set_pruebas[9], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 61, 'Folio' => $folios[61] + 4, 'MntBruto' => 1], 'Totales' => ['MntNeto' => 0, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]], 'Detalle' => [['QtyItem' => $set_pruebas[9]['Detalle'][0]['QtyItem'] * 0.4]], 'Referencia' => ['TpoDocRef' => $set_pruebas[9]['Encabezado']['IdDoc']['TipoDTE'], 'FolioRef' => $set_pruebas[9]['Encabezado']['IdDoc']['Folio'], 'CodRef' => 3, 'RazonRef' => 'SE REBAJA EN UN 40%']])]; // generar cada DTE, timbrar, firmar y agregar al sobre de EnvioDTE $EnvioDTE = new \sasco\LibreDTE\Sii\EnvioDte(); foreach ($notas_credito as $documento) { $DTE = new \sasco\LibreDTE\Sii\Dte($documento); if (!$DTE->timbrar($Folios[$DTE->getTipo()])) { break; } if (!$DTE->firmar($Firma)) { break; } $EnvioDTE->agregar($DTE); } $EnvioDTE->setFirma($Firma); $EnvioDTE->setCaratula($caratula); $EnvioDTE->generar();
/** * Acción para mostrar página de emisión de DTE * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl) * @version 2016-01-02 */ public function emitir($referencia_dte = null, $referencia_folio = null) { $Emisor = $this->getContribuyente(); if ($referencia_dte and $referencia_folio) { $DteEmitido = new Model_DteEmitido($Emisor->rut, $referencia_dte, $referencia_folio, (int) $Emisor->certificacion); if (!$DteEmitido->exists()) { \sowerphp\core\Model_Datasource_Session::message('Documento T' . $referencia_dte . 'F' . $referencia_folio . ' no existe, no se puede referenciar', 'error'); $this->redirect('/dte/dte_emitidos'); } $DteEmisor = $DteEmitido->getDatos()['Encabezado']['Emisor']; $DteReceptor = $DteEmitido->getDatos()['Encabezado']['Receptor']; $Comunas = new \sowerphp\app\Sistema\General\DivisionGeopolitica\Model_Comunas(); $DteEmisor['CmnaOrigen'] = $Comunas->getComunaByName($DteEmisor['CmnaOrigen']); $DteReceptor['CmnaRecep'] = $Comunas->getComunaByName($DteReceptor['CmnaRecep']); $this->set(['DteEmitido' => $DteEmitido, 'DteEmisor' => $DteEmisor, 'DteReceptor' => $DteReceptor]); } $this->set(['_header_extra' => ['js' => ['/dte/js/dte.js'], 'css' => ['/dte/css/dte.css']], 'Emisor' => $Emisor, 'actividades_economicas' => (new \website\Sistema\General\Model_ActividadEconomicas())->getList(), 'comunas' => (new \sowerphp\app\Sistema\General\DivisionGeopolitica\Model_Comunas())->getList(), 'tasa' => \sasco\LibreDTE\Sii::getIVA(), 'tipos_dte' => $Emisor->getDocumentosAutorizados(), 'tipos_referencia' => (new \website\Dte\Admin\Model_DteReferenciaTipos())->getList(), 'IndTraslado' => $this->IndTraslado]); }
/** * Método que normaliza los datos de una guía de despacho electrónica * @param datos Arreglo con los datos del documento que se desean normalizar * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-10-02 */ private function normalizar_52(array &$datos) { // completar con nodos por defecto $datos = \sasco\LibreDTE\Arreglo::mergeRecursiveDistinct(['Encabezado' => ['IdDoc' => false, 'Emisor' => false, 'Receptor' => false, 'Transporte' => false, 'Totales' => ['MntNeto' => 0, 'MntExe' => false, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]]], $datos); // si es traslado interno se copia el emisor en el receptor sólo si el // receptor no está definido o bien se el receptor tiene RUT diferente // al emisor if ($datos['Encabezado']['IdDoc']['IndTraslado'] == 5) { if (!$datos['Encabezado']['Receptor'] or $datos['Encabezado']['Receptor']['RUTRecep'] != $datos['Encabezado']['Emisor']['RUTEmisor']) { $datos['Encabezado']['Receptor'] = []; $cols = ['RUTEmisor' => 'RUTRecep', 'RznSoc' => 'RznSocRecep', 'GiroEmis' => 'GiroRecep', 'Telefono' => 'Contacto', 'CorreoEmisor' => 'CorreoRecep', 'DirOrigen' => 'DirRecep', 'CmnaOrigen' => 'CmnaRecep']; foreach ($cols as $emisor => $receptor) { if (!empty($datos['Encabezado']['Emisor'][$emisor])) { $datos['Encabezado']['Receptor'][$receptor] = $datos['Encabezado']['Emisor'][$emisor]; } } } } // normalizar datos $this->normalizar_detalle($datos); $this->normalizar_aplicar_descuentos_recargos($datos, ['MntNeto', 'MntExe']); $this->normalizar_agregar_IVA_MntTotal($datos); }
* @version 2015-09-16 */ // respuesta en texto plano header('Content-type: text/plain; charset=ISO-8859-1'); // incluir archivos php de la biblioteca y configuraciones include 'inc.php'; // primer folio a usar para envío de documentos de simulación $folios = [33 => 47, 34 => 39, 56 => 23, 61 => 45]; // caratula para el envío de los dte $caratula = ['RutEnvia' => '11222333-4', 'RutReceptor' => '60803000-K', 'FchResol' => '2014-12-05', 'NroResol' => 0]; // datos del emisor $Emisor = ['RUTEmisor' => '76192083-9', 'RznSoc' => 'SASCO SpA', 'GiroEmis' => 'Servicios integrales de informática', 'Acteco' => 726000, 'DirOrigen' => 'Santiago', 'CmnaOrigen' => 'Santiago']; // datos del receptor $Receptor = ['RUTRecep' => '55666777-8', 'RznSocRecep' => 'Empresa S.A.', 'GiroRecep' => 'Servicios jurídicos', 'DirRecep' => 'Santiago', 'CmnaRecep' => 'Santiago']; // datos de los DTE (cada elemento del arreglo $documentos es un DTE) $documentos = [['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => $folios[33]], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Antena ranurada 16 dBi', 'QtyItem' => 1, 'PrcItem' => 70000]]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => $folios[33] + 1], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Punto de acceso WAP54G', 'QtyItem' => 1, 'PrcItem' => 35000], ['NmbItem' => 'Pigtail LMR-195', 'QtyItem' => 1, 'PrcItem' => 10000], ['NmbItem' => 'Antena omnidireccional 14 dBi', 'QtyItem' => 1, 'PrcItem' => 25000]]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => $folios[33] + 2], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Ubiquiti Loco M5', 'QtyItem' => 2, 'PrcItem' => 35000]]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => $folios[33] + 3], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Ubiquiti Loco M2', 'QtyItem' => 2, 'PrcItem' => 35000, 'DescuentoPct' => 10]]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => $folios[33] + 4], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Ubiquiti Loco M2', 'QtyItem' => 2, 'PrcItem' => 35000]], 'DscRcgGlobal' => ['TpoMov' => 'D', 'TpoValor' => '%', 'ValorDR' => 6]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => $folios[33] + 5], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Ubiquiti Loco M2', 'QtyItem' => 2, 'PrcItem' => 35000]], 'DscRcgGlobal' => ['TpoMov' => 'D', 'TpoValor' => '$', 'ValorDR' => 5000]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => $folios[33] + 6], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Ubiquiti Loco M2', 'QtyItem' => 10, 'PrcItem' => 35000, 'DescuentoPct' => 10]], 'DscRcgGlobal' => ['TpoMov' => 'D', 'TpoValor' => '$', 'ValorDR' => 5000]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => $folios[33] + 7], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Ubiquiti Loco M2', 'QtyItem' => 10, 'PrcItem' => 35000, 'DescuentoPct' => 10]], 'DscRcgGlobal' => ['TpoMov' => 'D', 'TpoValor' => '%', 'ValorDR' => 7]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => $folios[33] + 8], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Punto de acceso WAP54G', 'QtyItem' => 1, 'PrcItem' => 35000], ['NmbItem' => 'Pigtail LMR-195', 'QtyItem' => 1, 'PrcItem' => 10000], ['NmbItem' => 'Antena omnidireccional 14 dBi', 'QtyItem' => 1, 'PrcItem' => 25000]], 'DscRcgGlobal' => ['TpoMov' => 'D', 'TpoValor' => '%', 'ValorDR' => 6]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => $folios[33] + 9], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Punto de acceso WAP54G', 'QtyItem' => 1, 'PrcItem' => 35000], ['NmbItem' => 'Pigtail LMR-195', 'QtyItem' => 1, 'PrcItem' => 10000, 'DescuentoPct' => 50], ['NmbItem' => 'Antena omnidireccional 14 dBi', 'QtyItem' => 1, 'PrcItem' => 25000]], 'DscRcgGlobal' => ['TpoMov' => 'D', 'TpoValor' => '%', 'ValorDR' => 6]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 61, 'Folio' => $folios[61]], 'Emisor' => $Emisor, 'Receptor' => $Receptor, 'Totales' => ['MntTotal' => 0]], 'Detalle' => [['NmbItem' => 'Antena ranurada 16 dBi']], 'Referencia' => ['TpoDocRef' => 33, 'FolioRef' => $folios[33], 'CodRef' => 2, 'RazonRef' => 'Corrige dirección del receptor']], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 61, 'Folio' => $folios[61] + 1], 'Emisor' => $Emisor, 'Receptor' => $Receptor, 'Totales' => ['MntNeto' => 0, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]], 'Detalle' => [['NmbItem' => 'Ubiquiti Loco M2', 'QtyItem' => 2, 'PrcItem' => 35000, 'DescuentoPct' => 10]], 'Referencia' => ['TpoDocRef' => 33, 'FolioRef' => $folios[33] + 3, 'CodRef' => 1, 'RazonRef' => 'Anula factura']], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 61, 'Folio' => $folios[61] + 2], 'Emisor' => $Emisor, 'Receptor' => $Receptor, 'Totales' => ['MntNeto' => 0, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]], 'Detalle' => [['NmbItem' => 'Ubiquiti Loco M5', 'QtyItem' => 1, 'PrcItem' => 35000]], 'Referencia' => ['TpoDocRef' => 33, 'FolioRef' => $folios[33] + 2, 'CodRef' => 3, 'RazonRef' => 'Devolución mercadería']], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 56, 'Folio' => $folios[56]], 'Emisor' => $Emisor, 'Receptor' => $Receptor, 'Totales' => ['MntNeto' => 0, 'TasaIVA' => \sasco\LibreDTE\Sii::getIVA(), 'IVA' => 0, 'MntTotal' => 0]], 'Detalle' => [['NmbItem' => 'Ubiquiti Loco M2', 'QtyItem' => 1, 'PrcItem' => 35000]], 'Referencia' => ['TpoDocRef' => 61, 'FolioRef' => $folios[61] + 2, 'CodRef' => 1, 'RazonRef' => 'Anula nota de crédito electrónica']], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 33, 'Folio' => $folios[33] + 10], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Punto de acceso WAP54G', 'QtyItem' => 1, 'PrcItem' => 35000], ['IndExe' => 1, 'NmbItem' => 'Asesoría en instalación de AP', 'QtyItem' => 1, 'PrcItem' => 15000]]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 34, 'Folio' => $folios[34]], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Desarrollo y mantención webapp agosto', 'QtyItem' => 1, 'PrcItem' => 950000]]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 34, 'Folio' => $folios[34] + 1], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Desarrollo y mantención webapp agosto', 'QtyItem' => 1, 'PrcItem' => 950000], ['NmbItem' => 'Configuración en terreno de servidor web', 'QtyItem' => 1, 'PrcItem' => 80000]]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 34, 'Folio' => $folios[34] + 2], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Capacitación aplicación web', 'QtyItem' => 8, 'UnmdItem' => 'Hora', 'PrcItem' => 25000]]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 34, 'Folio' => $folios[34] + 3], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Desarrollo nueva funcionalidad', 'QtyItem' => 16, 'UnmdItem' => 'Hora', 'PrcItem' => 14000], ['NmbItem' => 'Capacitación nueva funcionalidad', 'QtyItem' => 2, 'UnmdItem' => 'Hora', 'PrcItem' => 25000]]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 34, 'Folio' => $folios[34] + 4], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Certificación facturación electrónica', 'QtyItem' => 1, 'PrcItem' => 599000]], 'DscRcgGlobal' => ['TpoMov' => 'D', 'TpoValor' => '%', 'ValorDR' => 50]], ['Encabezado' => ['IdDoc' => ['TipoDTE' => 34, 'Folio' => $folios[34] + 5], 'Emisor' => $Emisor, 'Receptor' => $Receptor], 'Detalle' => [['NmbItem' => 'Desarrolo interfaces para API LibreDTE', 'QtyItem' => 40, 'UnmdItem' => 'Hora', 'PrcItem' => 14000], ['NmbItem' => 'Capacitación API facturación electrónica', 'QtyItem' => 4, 'UnmdItem' => 'Hora', 'PrcItem' => 25000], ['NmbItem' => 'Certificación facturación electrónica', 'QtyItem' => 1, 'PrcItem' => 599000, 'DescuentoPct' => 50]]]]; // Objetos de Firma, Folios y EnvioDTE $Firma = new \sasco\LibreDTE\FirmaElectronica($config['firma']); $Folios = []; foreach ($folios as $tipo => $cantidad) { $Folios[$tipo] = new \sasco\LibreDTE\Sii\Folios(file_get_contents('xml/folios/' . $tipo . '.xml')); } $EnvioDTE = new \sasco\LibreDTE\Sii\EnvioDTE(); // generar cada DTE, timbrar, firmar y agregar al sobre de EnvioDTE foreach ($documentos as $documento) { $DTE = new \sasco\LibreDTE\Sii\Dte($documento); if (!$DTE->timbrar($Folios[$DTE->getTipo()])) { break; } if (!$DTE->firmar($Firma)) { break;
/** * Método que procesa el arreglo con los datos del set de pruebas y crea el * arreglo json con los documentos listos para ser pasados a la clase Dte * @param archivo Contenido del archivo del set de set de pruebas * @param separador usado en el archivo para los casos (son los "=" debajo del título del caso) * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-10-02 */ public static function getJSON($archivo, array $folios = [], $separador = '==============') { $documentos = []; $casos = self::parse($archivo, $separador); $referencias = []; foreach ($casos as $caso) { // determinar tipo documento y folio $TipoDTE = self::$tipos[$caso['documento']]; if (!isset($folios[$TipoDTE])) { $folios[$TipoDTE] = 1; } $Folio = $folios[$TipoDTE]; // crear encabezado del documento $documento = ['Encabezado' => ['IdDoc' => ['TipoDTE' => $TipoDTE, 'Folio' => $Folio]]]; // si es guía de despacho se agrega indicador de traslado if ($TipoDTE == 52) { if (isset($caso['traslado_por'])) { $documento['Encabezado']['IdDoc']['TipoDespacho'] = self::$TipoDespachos[$caso['traslado_por']]; } if (isset($caso['motivo'])) { $documento['Encabezado']['IdDoc']['IndTraslado'] = self::$IndTraslados[$caso['motivo']]; } } // agregar detalle del documento si fue pasado explícitamente if (isset($caso['detalle'])) { $documento['Detalle'] = []; foreach ($caso['detalle'] as $item) { // generar detalle del item $detalle = []; foreach ($item as $col => $val) { $col = self::$item_cols[$col]; // procesar cada valor de acuerdo al nombre de la columna if ($col == 'DescuentoPct') { $detalle[$col] = substr($val, 0, -1); } else { $detalle[$col] = utf8_encode($val); } // se convierte de ISO-8859-1 a UTF-8 } // si el item es EXENTO se agrega campo que lo indica if (strpos($detalle['NmbItem'], 'EXENTO')) { $detalle['IndExe'] = 1; } // si hay una referencia se completa con los campos del // detalle de la referencia que no estén en este detalle if (!empty($caso['referencia'])) { // buscar el caso y copiar sus columnas que no estén $detalle_r = $documentos[$caso['referencia']['caso']]['Detalle']; $n_detalle_r = count($detalle_r); for ($i = 0; $i < $n_detalle_r; $i++) { if ($detalle_r[$i]['NmbItem'] == $detalle['NmbItem']) { foreach ($detalle_r[$i] as $attr => $val) { if (!isset($detalle[$attr])) { $detalle[$attr] = $val; } } } } // si la referencia es a una factura exenta y existe un // precio entonces se marca como exento el item if ($documentos[$caso['referencia']['caso']]['Encabezado']['IdDoc']['TipoDTE'] == 34 and isset($detalle['PrcItem'])) { $detalle['IndExe'] = 1; } } // agregar detalle del item a los detalles $documento['Detalle'][] = $detalle; } } else { if (!empty($caso['referencia'])) { $referencia = self::getReferencia($caso['referencia']['razon']); // copiar todos los detalles if ($referencia['detalle'] == 1) { $documento['Detalle'] = $documentos[$caso['referencia']['caso']]['Detalle']; } else { if ($referencia['detalle'] == 2) { $documento['Detalle'] = [['NmbItem' => $documentos[$caso['referencia']['caso']]['Detalle'][0]['NmbItem']]]; } } } } // agregar descuento del documento if (!empty($caso['descuento'])) { $documento['DscRcgGlobal'] = ['TpoMov' => 'D', 'TpoValor' => '%', 'ValorDR' => substr($caso['descuento'], 0, -1)]; } else { if (!empty($caso['referencia']) and isset($documentos[$caso['referencia']['caso']]['DscRcgGlobal'])) { $documento['DscRcgGlobal'] = $documentos[$caso['referencia']['caso']]['DscRcgGlobal']; } } // agregar referencia obligatoria $documento['Referencia'] = []; $documento['Referencia'][] = ['TpoDocRef' => 'SET', 'FolioRef' => $folios[$TipoDTE], 'RazonRef' => 'CASO ' . $caso['caso']]; // agregar referencias del caso if (!empty($caso['referencia'])) { $referencia = self::getReferencia($caso['referencia']['razon']); // agregar referencia $documento['Referencia'][] = ['TpoDocRef' => $documentos[$caso['referencia']['caso']]['Encabezado']['IdDoc']['TipoDTE'], 'FolioRef' => $documentos[$caso['referencia']['caso']]['Encabezado']['IdDoc']['Folio'], 'CodRef' => $referencia['codigo'], 'RazonRef' => $caso['referencia']['razon']]; // agregar totales $documento['Encabezado']['Totales'] = $referencia['Totales']; // agregar tasa de IVA si corresponde if (isset($documento['Encabezado']['Totales']['TasaIVA'])) { $documento['Encabezado']['Totales']['TasaIVA'] = \sasco\LibreDTE\Sii::getIVA(); } // si el documento referenciado es factura exenta y hay MntExe if (isset($documento['Encabezado']['Totales']['MntExe'])) { if ($documentos[$caso['referencia']['caso']]['Encabezado']['IdDoc']['TipoDTE'] == 34) { $documento['Encabezado']['Totales']['MntExe'] = 0; } else { unset($documento['Encabezado']['Totales']['MntExe']); } } } // si hay Totales pero no hay valores en los detalles entonces se cambia a sólo Totales de MntTotal = 0 if (isset($documento['Encabezado']['Totales'])) { $hayValor = false; foreach ($documento['Detalle'] as $d) { if (!empty($d['PrcItem'])) { $hayValor = true; } } if (!$hayValor) { if (isset($documento['Encabezado']['Totales']['MntExe'])) { $documento['Encabezado']['Totales'] = ['MntExe' => 0]; } else { $documento['Encabezado']['Totales'] = []; } $documento['Encabezado']['Totales']['MntTotal'] = 0; } } // agregar documento a los documentos $documentos[$caso['caso']] = $documento; // pasar al siguiente folio de este tipo; $folios[$TipoDTE]++; } // pasar de índice "número de caso" a índice numérico, o sea // pasar de diccionario o hash a arreglo antes convertir a JSON $aux = $documentos; $documentos = []; foreach ($aux as $d) { $documentos[] = $d; } // retornar documentos return json_encode($documentos, JSON_PRETTY_PRINT); }