/** * Método que entrega el objeto del contribuyente que ha sido seleccionado * @return \website\Dte\Model_Contribuyente * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2016-01-02 */ protected function getContribuyente() { if (!isset($this->Contribuyente)) { $this->Contribuyente = \sowerphp\core\Model_Datasource_Session::read('dte.Contribuyente'); } return $this->Contribuyente; }
/** * Acción que descarga el XML de la recepción * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-23 */ public function xml($responde, $codigo) { $Emisor = $this->getContribuyente(); // obtener Recepción $DteIntercambioRecepcion = new Model_DteIntercambioRecepcion($responde, $Emisor->rut, $codigo); if (!$DteIntercambioRecepcion->exists()) { \sowerphp\core\Model_Datasource_Session::message('No existe la recepción solicitada', 'error'); $this->redirect('/dte/dte_intercambios'); } // entregar XML $xml = base64_decode($DteIntercambioRecepcion->xml); header('Content-Type: application/xml; charset=ISO-8859-1'); header('Content-Length: ' . strlen($xml)); header('Content-Disposition: attachement; filename="' . $DteIntercambioRecepcion->responde . '_' . $DteIntercambioRecepcion->codigo . '.xml"'); print $xml; exit; }
/** * Método que fuerza la selección de un contribuyente * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-12 */ public function beforeFilter() { parent::beforeFilter(); // configuración previa para el módulo Dte y sus submódulos if (strpos($this->request->params['module'], 'Dte') === 0 and $this->request->params['controller'] != 'contribuyentes' and !$this->Auth->allowedWithoutLogin()) { // obtener emisor $Emisor = \sowerphp\core\Model_Datasource_Session::read('dte.Emisor'); if (!$Emisor) { \sowerphp\core\Model_Datasource_Session::message('Antes de utilizar el módulo DTE debe seleccionar un contribuyente con el que operará', 'error'); \sowerphp\core\Model_Datasource_Session::write('referer', $this->request->request); $this->redirect('/dte/contribuyentes/seleccionar'); } // si no existe la definición de ambiente y es de certificación se asigna if (!defined('_LibreDTE_CERTIFICACION_') and $Emisor->certificacion) { define('_LibreDTE_CERTIFICACION_', true); } } }
/** * Acción que muestra la página principal de estadísticas * @param certificacion =true se generan estadísticas para el ambiente de certificación * @param desde Desde cuando considerar la actividad de los contribuyentes * @param hasta Hasta cuando considerar la actividad de los contribuyentes * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2016-01-07 */ public function index($certificacion = false, $desde = 1, $hasta = 0) { $Contribuyentes = new \website\Dte\Model_Contribuyentes(); $contribuyentes_sii = $Contribuyentes->count(); $Contribuyentes->setWhereStatement(['usuario IS NOT NULL', 'certificacion = :certificacion'], [':certificacion' => (int) $certificacion]); $empresas_registradas = $Contribuyentes->count(); $DteEmitidos = new \website\Dte\Model_DteEmitidos(); $DteEmitidos->setWhereStatement(['certificacion = :certificacion'], [':certificacion' => (int) $certificacion]); $Usuarios = new \sowerphp\app\Sistema\Usuarios\Model_Usuarios(); $Usuarios->setWhereStatement(['activo = true']); try { $contribuyentes_activos = $Contribuyentes->getConMovimientos($desde, $hasta, $certificacion, false); } catch (\sowerphp\core\Exception_Model_Datasource_Database $e) { \sowerphp\core\Model_Datasource_Session::message($e->getMessage(), 'error'); $contribuyentes_activos = []; } $this->set(['certificacion' => $certificacion, 'contribuyentes_sii' => $contribuyentes_sii, 'usuarios_registrados' => $Usuarios->count(), 'empresas_registradas' => $empresas_registradas, 'documentos_emitidos' => $DteEmitidos->count(), 'contribuyentes_activos' => $contribuyentes_activos]); $this->autoRender = false; $this->render('Estadisticas/index'); }
/** * Acción para la etapa de certificación de intercambio de DTEs * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-11 */ public function intercambio() { $this->set(['nav' => $this->nav]); if (!isset($_POST['submit'])) { return; } // verificar que se hayan pasado los datos requeridos if (!isset($_FILES['xml']) or $_FILES['xml']['error']) { \sowerphp\core\Model_Datasource_Session::message('Hubo algún problema al subir el XML EnvioDTE', 'error'); return; } if (empty($_POST['emisor'])) { \sowerphp\core\Model_Datasource_Session::message('RUT emisor esperado no puede estar en blanco', 'error'); return; } if (empty($_POST['receptor'])) { \sowerphp\core\Model_Datasource_Session::message('RUT receptor esperado no puede estar en blanco', 'error'); return; } if (!isset($_FILES['firma']) or $_FILES['firma']['error']) { \sowerphp\core\Model_Datasource_Session::message('Hubo algún problema al subir la firma electrónica', 'error'); return; } // Cargar EnvioDTE y extraer arreglo con datos de carátula y DTEs $EnvioDte = new \sasco\LibreDTE\Sii\EnvioDte(); $EnvioDte->loadXML(file_get_contents($_FILES['xml']['tmp_name'])); $Caratula = $EnvioDte->getCaratula(); // objeto firma electrónica try { $Firma = new \sasco\LibreDTE\FirmaElectronica(['data' => file_get_contents($_FILES['firma']['tmp_name']), 'pass' => $_POST['contrasenia']]); } catch (\Exception $e) { \sowerphp\core\Model_Datasource_Session::message('No fue posible abrir la firma digital, quizás contraseña incorrecta', 'error'); return; } // generar XML RecepcionDTE.xml $RecepcionDTE = $this->intercambio_RecepcionDTE($EnvioDte, $_POST['emisor'], $_POST['receptor'], ['RutResponde' => $_POST['receptor'], 'RutRecibe' => $Caratula['RutEmisor'], 'IdRespuesta' => 1, 'NmbContacto' => $Firma->getName(), 'MailContacto' => $Firma->getEmail()], $Firma); if (!$RecepcionDTE) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar RecepcionDTE.xml', 'error'); return; } // generar XML EnvioRecibos.xml $EnvioRecibos = $this->intercambio_EnvioRecibos($EnvioDte, ['RutResponde' => $_POST['receptor'], 'RutRecibe' => $Caratula['RutEmisor'], 'NmbContacto' => $Firma->getName(), 'MailContacto' => $Firma->getEmail()], $Firma); if (!$EnvioRecibos) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar EnvioRecibos.xml', 'error'); return; } // generar XML ResultadoDTE.xml $ResultadoDTE = $this->intercambio_ResultadoDTE($EnvioDte, $_POST['emisor'], $_POST['receptor'], ['RutResponde' => $_POST['receptor'], 'RutRecibe' => $Caratula['RutEmisor'], 'IdRespuesta' => 1, 'NmbContacto' => $Firma->getName(), 'MailContacto' => $Firma->getEmail()], $Firma); if (!$ResultadoDTE) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar ResultadoDTE.xml', 'error'); return; } // aquí se tienen los 3 XML, se guardan en un único directorio $dir = TMP . '/intercambio_' . $Caratula['RutEmisor'] . '_' . date('U'); if (!mkdir($dir)) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar el archivo comprimido con los XML', 'error'); return; } file_put_contents($dir . '/1_RecepcionDTE.xml', $RecepcionDTE); file_put_contents($dir . '/2_EnvioRecibos.xml', $EnvioRecibos); file_put_contents($dir . '/3_ResultadoDTE.xml', $ResultadoDTE); unset($RecepcionDTE, $EnvioRecibos, $ResultadoDTE); // entregar archivos XML comprimidos al usuario \sasco\LibreDTE\File::compress($dir, ['format' => 'zip', 'delete' => true]); }
/** * Método que permite generar un libro de Compras o Ventas a partir de un * archivo CSV con el detalle del mismo * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-10-05 */ public function generar_libro() { // si no se viene por post terminar if (!isset($_POST['submit'])) { return; } // verificar campos no estén vacíos $campos = ['TipoOperacion', 'RutEmisorLibro', 'PeriodoTributario', 'FchResol', 'NroResol', 'TipoLibro', 'TipoEnvio', 'FolioNotificacion', 'contrasenia']; foreach ($campos as $campo) { if (empty($_POST[$campo])) { \sowerphp\core\Model_Datasource_Session::message($campo . ' no puede estar en blanco', 'error'); return; } } // si no se pasó el archivo error if (!isset($_FILES['archivo']) or $_FILES['archivo']['error']) { \sowerphp\core\Model_Datasource_Session::message('Debes enviar el archivo CSV con el detalle de las compras o ventas al que deseas generar su XML', 'error'); return; } // si no se pasó la firma error if (!isset($_FILES['firma']) or $_FILES['firma']['error']) { \sowerphp\core\Model_Datasource_Session::message('Debes enviar el archivo con la firma digital', 'error'); return; } // Objeto de la Firma try { $Firma = new \sasco\LibreDTE\FirmaElectronica(['data' => file_get_contents($_FILES['firma']['tmp_name']), 'pass' => $_POST['contrasenia']]); } catch (\Exception $e) { \sowerphp\core\Model_Datasource_Session::message('No fue posible abrir la firma digital, quizás contraseña incorrecta', 'error'); return; } // generar caratula del libro $caratula = ['RutEmisorLibro' => str_replace('.', '', $_POST['RutEmisorLibro']), 'RutEnvia' => $Firma->getID(), 'PeriodoTributario' => $_POST['PeriodoTributario'], 'FchResol' => $_POST['FchResol'], 'NroResol' => $_POST['NroResol'], 'TipoOperacion' => $_POST['TipoOperacion'], 'TipoLibro' => $_POST['TipoLibro'], 'TipoEnvio' => $_POST['TipoEnvio'], 'FolioNotificacion' => $_POST['FolioNotificacion']]; // definir si es certificacion $caratula_certificacion = ['COMPRA' => ['PeriodoTributario' => 2000, 'FchResol' => '2006-01-20', 'NroResol' => 102006, 'TipoLibro' => 'ESPECIAL', 'TipoEnvio' => 'TOTAL', 'FolioNotificacion' => 102006], 'VENTA' => ['PeriodoTributario' => 1980, 'FchResol' => '2006-01-20', 'NroResol' => 102006, 'TipoLibro' => 'ESPECIAL', 'TipoEnvio' => 'TOTAL', 'FolioNotificacion' => 102006]]; $certificacion = true; foreach ($caratula_certificacion[$caratula['TipoOperacion']] as $attr => $val) { if ($caratula[$attr] != $val or $attr == 'PeriodoTributario' and substr($caratula[$attr], 0, 4) != $val) { $certificacion = false; break; } } // generar libro de compras o venta $LibroCompraVenta = new \sasco\LibreDTE\Sii\LibroCompraVenta(); if ($caratula['TipoOperacion'] === 'COMPRA') { $LibroCompraVenta->agregarComprasCSV($_FILES['archivo']['tmp_name']); } else { $LibroCompraVenta->agregarVentasCSV($_FILES['archivo']['tmp_name']); } $LibroCompraVenta->setCaratula($caratula); if (!$certificacion) { $LibroCompraVenta->setFirma($Firma); } $xml = $LibroCompraVenta->generar($caratula['TipoOperacion'] == 'COMPRA'); if (!$certificacion and !$LibroCompraVenta->schemaValidate()) { \sowerphp\core\Model_Datasource_Session::message(implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error'); return; } // descargar XML $file = TMP . '/' . $LibroCompraVenta->getID() . '.xml'; file_put_contents($file, $xml); \sasco\LibreDTE\File::compress($file, ['format' => 'zip', 'delete' => true]); exit; }
/** * Acción que permite modificar un mantenedor de folios * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-29 */ public function modificar($dte) { $Emisor = $this->getContribuyente(); $DteFolio = new Model_DteFolio($Emisor->rut, $dte, (int) $Emisor->certificacion); if (!$DteFolio->exists()) { \sowerphp\core\Model_Datasource_Session::message('No existe el mantenedor de folios solicitado', 'error'); $this->redirect('/dte/admin/dte_folios'); } $this->set(['Emisor' => $Emisor, 'DteFolio' => $DteFolio]); if (isset($_POST['submit'])) { // validar que campos existan y asignar foreach (['siguiente', 'alerta'] as $attr) { if (empty($_POST[$attr])) { \sowerphp\core\Model_Datasource_Session::message('Debe especificar el campo: ' . $attr, 'error'); return; } $DteFolio->{$attr} = $_POST[$attr]; } // guardar y redireccionar try { $DteFolio->calcularDisponibles(); \sowerphp\core\Model_Datasource_Session::message('Mantenedor de folios para tipo ' . $DteFolio->dte . ' actualizado', 'ok'); $this->redirect('/dte/admin/dte_folios'); } catch (\sowerphp\core\Exception_Model_Datasource_Database $e) { \sowerphp\core\Model_Datasource_Session::message('No fue posible actualizar el mantenedor de folios: ' . $e->getMessage(), 'error'); return; } } }
/** * Acción que envía por email el PDF y el XML del DTE * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-12 */ public function enviar_email($dte, $folio) { $Emisor = $this->getContribuyente(); // obtener DTE emitido $DteEmitido = new Model_DteEmitido($Emisor->rut, $dte, $folio, (int) $Emisor->certificacion); if (!$DteEmitido->exists()) { \sowerphp\core\Model_Datasource_Session::message('No existe el DTE solicitado', 'error'); $this->redirect('/dte/dte_emitidos/listar'); } // se verifican datos mínimos foreach (['emails', 'asunto', 'mensaje'] as $attr) { if (empty($_POST[$attr])) { \sowerphp\core\Model_Datasource_Session::message('Debe especificar el campo: ' . $attr, 'error'); $this->redirect(str_replace('enviar_email', 'ver', $this->request->request) . '#email'); } } // crear email $email = $Emisor->getEmailSmtp(); $email->to($_POST['emails']); $email->subject($_POST['asunto']); // adjuntar PDF $data = ['xml' => $DteEmitido->xml, 'cedible' => isset($_POST['cedible']), 'compress' => false]; $logo = \sowerphp\core\Configure::read('dte.logos.dir') . '/' . $Emisor->rut . '.png'; if (is_readable($logo)) { $data['logo'] = base64_encode(file_get_contents($logo)); } $rest = new \sowerphp\core\Network_Http_Rest(); $rest->setAuth($this->Auth->User->hash); $response = $rest->post($this->request->url . '/api/dte/documentos/generar_pdf', $data); if ($response['status']['code'] != 200) { \sowerphp\core\Model_Datasource_Session::message($response['body'], 'error'); $this->redirect(str_replace('enviar_email', 'ver', $this->request->request) . '#email'); } $email->attach(['data' => $response['body'], 'name' => 'dte_' . $Emisor->rut . '-' . $Emisor->dv . '_T' . $DteEmitido->dte . 'F' . $DteEmitido->folio . '.pdf', 'type' => 'application/pdf']); // adjuntar XML $email->attach(['data' => base64_decode($DteEmitido->xml), 'name' => 'dte_' . $Emisor->rut . '-' . $Emisor->dv . '_T' . $DteEmitido->dte . 'F' . $DteEmitido->folio . '.xml', 'type' => 'application/xml']); // enviar email $status = $email->send($_POST['mensaje']); if ($status === true) { \sowerphp\core\Model_Datasource_Session::message('Se envió el DTE a: ' . implode(', ', $_POST['emails']), 'ok'); $this->redirect(str_replace('enviar_email', 'ver', $this->request->request)); } else { \sowerphp\core\Model_Datasource_Session::message('No fue posible enviar el email, por favor intente nuevamente.<br /><em>' . $status['message'] . '</em>', 'error'); $this->redirect(str_replace('enviar_email', 'ver', $this->request->request) . '#email'); } }
/** * Acción que permite subir un XML con el resultado de la revisión * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-26 */ public function subir_revision($periodo) { $Emisor = $this->getContribuyente(); // obtener libro envíado $class = __NAMESPACE__ . '\\Model_Dte' . $this->config['model']['singular']; $Libro = new $class($Emisor->rut, (int) $periodo, (int) $Emisor->certificacion); if (!$Libro->exists()) { \sowerphp\core\Model_Datasource_Session::message('Aun no se ha generado el libro del período ' . $periodo, 'error'); $this->redirect(str_replace('subir_revision', 'ver', $this->request->request)); } // si no tiene track id error if (!$Libro->track_id) { \sowerphp\core\Model_Datasource_Session::message('Libro del período ' . $periodo . ' no tiene Track ID, primero debe enviarlo al SII', 'error'); $this->redirect(str_replace('subir_revision', 'ver', $this->request->request)); } // si no se viene por post o el archivo no se subió o dió error if (!isset($_POST['submit']) or !isset($_FILES['xml']) or $_FILES['xml']['error']) { \sowerphp\core\Model_Datasource_Session::message('Debe subir archivo XML con la revisión', 'ok'); $this->redirect(str_replace('subir_revision', 'ver', $this->request->request) . '#revision'); } // guardar revisión $status = $Libro->saveRevision(file_get_contents($_FILES['xml']['tmp_name'])); if ($status === true) { \sowerphp\core\Model_Datasource_Session::message('Se actualizó el estado del envío del libro', 'ok'); } else { \sowerphp\core\Model_Datasource_Session::message('No fue posible guardar el estado del libro en la base de datos<br/>' . $status, 'error'); } $this->redirect(str_replace('subir_revision', 'ver', $this->request->request)); }
/** * Método que agrega o modifica un DTE recibido * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-28 */ private function save() { $Emisor = $this->getContribuyente(); // revisar datos minimos foreach (['emisor', 'dte', 'folio', 'fecha', 'tasa'] as $attr) { if (!isset($_POST[$attr][0])) { \sowerphp\core\Model_Datasource_Session::message('Debe indicar ' . $attr, 'error'); return; } } // crear dte recibido list($emisor, $dv) = explode('-', str_replace('.', '', $_POST['emisor'])); $DteRecibido = new Model_DteRecibido($emisor, $_POST['dte'], (int) $_POST['folio'], (int) $Emisor->certificacion); $DteRecibido->receptor = $Emisor->rut; $DteRecibido->tasa = (int) $_POST['tasa']; $DteRecibido->fecha = $_POST['fecha']; $DteRecibido->exento = !empty($_POST['exento']) ? $_POST['exento'] : null; $DteRecibido->neto = !empty($_POST['neto']) ? $_POST['neto'] : null; $DteRecibido->iva = round((int) $DteRecibido->neto * ($DteRecibido->tasa / 100)); $DteRecibido->total = (int) $DteRecibido->exento + (int) $DteRecibido->neto + $DteRecibido->iva; $DteRecibido->usuario = $this->Auth->User->id; // iva uso común, no recuperable e impuesto adicional $DteRecibido->iva_uso_comun = !empty($_POST['iva_uso_comun']) ? $_POST['iva_uso_comun'] : null; $DteRecibido->iva_no_recuperable = !empty($_POST['iva_no_recuperable']) ? $_POST['iva_no_recuperable'] : null; if (!empty($_POST['impuesto_adicional']) and !empty($_POST['impuesto_adicional_tasa'])) { $DteRecibido->impuesto_adicional = $_POST['impuesto_adicional']; $DteRecibido->impuesto_adicional_tasa = $_POST['impuesto_adicional_tasa']; } else { $DteRecibido->impuesto_adicional = null; $DteRecibido->impuesto_adicional_tasa = null; } $DteRecibido->impuesto_tipo = $_POST['impuesto_tipo']; $DteRecibido->anulado = isset($_POST['anulado']) ? 'A' : null; $DteRecibido->impuesto_sin_credito = !empty($_POST['impuesto_sin_credito']) ? $_POST['impuesto_sin_credito'] : null; $DteRecibido->monto_activo_fijo = !empty($_POST['monto_activo_fijo']) ? $_POST['monto_activo_fijo'] : null; $DteRecibido->monto_iva_activo_fijo = !empty($_POST['monto_iva_activo_fijo']) ? $_POST['monto_iva_activo_fijo'] : null; $DteRecibido->iva_no_retenido = !empty($_POST['iva_no_retenido']) ? $_POST['iva_no_retenido'] : null; // si el DTE es de producción y es electrónico entonces se consultará su // estado antes de poder guardar, esto evitará agregar documentos que no // han sido recibidos en el SII o sus datos son incorrectos if (!$Emisor->certificacion and $DteRecibido->getTipo()->electronico) { // obtener firma $Firma = $Emisor->getFirma($this->Auth->User->id); if (!$Firma) { \sowerphp\core\Model_Datasource_Session::message('No hay firma electrónica asociada a la empresa (o bien no se pudo cargar), debe agregar su firma antes de generar DTE', 'error'); $this->redirect('/dte/admin/firma_electronicas'); } // consultar estado dte $estado = $DteRecibido->getEstado($Firma); if ($estado === false) { \sowerphp\core\Model_Datasource_Session::message('No se pudo obtener el estado del DTE.<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error'); return; } else { if (is_string($estado)) { \sowerphp\core\Model_Datasource_Session::message('Estado DTE: ' . $estado, 'error'); return; } } } // todo ok con el dte así que se agrega a los dte recibidos try { $DteRecibido->save(); \sowerphp\core\Model_Datasource_Session::message('DTE recibido guardado', 'ok'); $this->redirect('/dte/dte_recibidos/listar'); } catch (\sowerphp\core\Exception_Model_Datasource_Database $e) { \sowerphp\core\Model_Datasource_Session::message('No fue posible guardar el DTE: ' . $e->getMessage(), 'error'); } }
/** * Método que elimina un DTE temporal * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl) * @version 2015-09-23 */ public function eliminar($receptor, $dte, $codigo) { $Emisor = $this->getContribuyente(); // obtener DTE temporal $DteTmp = new Model_DteTmp($Emisor->rut, $receptor, $dte, $codigo); if (!$DteTmp->exists()) { \sowerphp\core\Model_Datasource_Session::message('No existe el DTE temporal solicitado', 'error'); $this->redirect('/dte/dte_tmps'); } // eliminar try { $DteTmp->delete(); \sowerphp\core\Model_Datasource_Session::message('DTE temporal eliminado', 'ok'); $this->redirect('/dte/dte_tmps'); } catch (\sowerphp\core\Exception_Model_Datasource_Database $e) { \sowerphp\core\Model_Datasource_Session::message('No fue posible eliminar el DTE temporal: ' . $e->getMessage()); $this->redirect('/dte/dte_tmps'); } }
/** * Método que genera la el XML del DTE temporal con Folio y Firma y lo envía * al SII * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl) * @version 2016-01-02 */ public function generar($receptor, $dte, $codigo) { $Emisor = $this->getContribuyente(); // obtener DTE temporal $DteTmp = new Model_DteTmp($Emisor->rut, $receptor, $dte, $codigo); if (!$DteTmp->exists()) { \sowerphp\core\Model_Datasource_Session::message('No existe el DTE temporal solicitado', 'error'); $this->redirect('/dte/documentos/emitir'); } // obtener firma electrónica $Firma = $Emisor->getFirma($this->Auth->User->id); if (!$Firma) { \sowerphp\core\Model_Datasource_Session::message('No hay firma electrónica asociada a la empresa (o bien no se pudo cargar), debe agregar su firma antes de generar DTE', 'error'); $this->redirect('/dte/admin/firma_electronicas'); } // solicitar folio $FolioInfo = $Emisor->getFolio($DteTmp->dte); if (!$FolioInfo) { \sowerphp\core\Model_Datasource_Session::message('No fue posible obtener un folio para el DTE de tipo ' . $DteTmp->dte, 'error'); $this->redirect('/dte/dte_tmps'); } // si quedan pocos folios y se debe alertar al usuario admnistrador de la empresa se hace if ($FolioInfo->DteFolio->disponibles <= $FolioInfo->DteFolio->alerta and !$FolioInfo->DteFolio->alertado) { $msg = 'Se ha alcanzado el límite de folios del tipo de DTE ' . $FolioInfo->DteFolio->dte . ' para el contribuyente ' . $Emisor->razon_social . ', quedan ' . $FolioInfo->DteFolio->disponibles . '. Por favor, solicite un nuevo archivo CAF y súbalo en: ' . "\n\n" . $this->request->url . '/dte/admin/dte_folios'; if ($this->Notify->send(null, $Emisor->getUsuario()->id, $msg, 'email')) { $FolioInfo->DteFolio->alertado = 1; $FolioInfo->DteFolio->save(); } } // armar xml a partir de json del DTE temporal $EnvioDte = $DteTmp->getEnvioDte($FolioInfo->folio, $FolioInfo->Caf, $Firma); $xml = $EnvioDte->generar(); if (!$xml) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar el XML del EnvioDTE. Folio ' . $FolioInfo->folio . ' quedará sin usar.<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error'); $this->redirect('/dte/documentos/emitir'); } // guardar DTE $r = $EnvioDte->getDocumentos()[0]->getResumen(); $DteEmitido = new Model_DteEmitido($Emisor->rut, $r['TpoDoc'], $r['NroDoc'], (int) $Emisor->certificacion); if ($DteEmitido->exists()) { \sowerphp\core\Model_Datasource_Session::message('Ya existe un DTE del tipo ' . $r['TpoDoc'] . ' y folio ' . $r['NroDoc'] . ' emitido', 'error'); $this->redirect('/dte/dte_emitidos/ver/' . $r['TpoDoc'] . '/' . $r['NroDoc'] . '/' . (int) $Emisor->certificacion); } $cols = ['tasa' => 'TasaImp', 'fecha' => 'FchDoc', 'sucursal_sii' => 'CdgSIISucur', 'receptor' => 'RUTDoc', 'exento' => 'MntExe', 'neto' => 'MntNeto', 'iva' => 'MntIVA', 'total' => 'MntTotal']; foreach ($cols as $attr => $col) { if ($r[$col] !== false) { $DteEmitido->{$attr} = $r[$col]; } } $DteEmitido->receptor = substr($DteEmitido->receptor, 0, -2); $DteEmitido->xml = base64_encode($xml); $DteEmitido->usuario = $this->Auth->User->id; // guardar referencias si existen $datos = json_decode($DteTmp->datos, true); if (isset($datos['Referencia'])) { foreach ($datos['Referencia'] as $referencia) { $DteReferencia = new Model_DteReferencia(); $DteReferencia->emisor = $DteEmitido->emisor; $DteReferencia->dte = $DteEmitido->dte; $DteReferencia->folio = $DteEmitido->folio; $DteReferencia->certificacion = $DteEmitido->certificacion; $DteReferencia->referencia_dte = $referencia['TpoDocRef']; $DteReferencia->referencia_folio = $referencia['FolioRef']; $DteReferencia->codigo = !empty($referencia['CodRef']) ? $referencia['CodRef'] : null; $DteReferencia->razon = !empty($referencia['RazonRef']) ? $referencia['RazonRef'] : null; $DteReferencia->save(); } } // eliminar DTE temporal $DteTmp->delete(); // enviar DTE al SII y redireccionar a página del DTE $track_id = $EnvioDte->enviar(); if ($track_id) { $DteEmitido->track_id = $track_id; \sowerphp\core\Model_Datasource_Session::message('Documento emitido y envíado al SII, ahora debe verificar estado del envío. TrackID: ' . $track_id, 'ok'); } else { \sowerphp\core\Model_Datasource_Session::message('Documento emitido, pero no pudo ser envíado al SII, debe reenviar.<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'warning'); } $DteEmitido->save(); $this->redirect('/dte/dte_emitidos/ver/' . $r['TpoDoc'] . '/' . $r['NroDoc'] . '/' . (int) $Emisor->certificacion); }
/** * Acción que descarga la firma electrónica de un usuario * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-10-05 */ public function descargar() { $FirmaElectronica = (new Model_FirmaElectronicas())->getByUser($this->Auth->User->id); // si el usuario no tiene firma electrónica no se elimina :-) if (!$FirmaElectronica) { \sowerphp\core\Model_Datasource_Session::message('Usted no tiene una firma electrónica registrada en el sistema, no hay nada que descargar'); $this->redirect('/dte/admin/firma_electronicas'); } // descargar la firma $file = $FirmaElectronica->run . '.p12'; $firma = base64_decode($FirmaElectronica->archivo); header('Content-Type: application/x-pkcs12'); header('Content-Length: ' . strlen($firma)); header('Content-Disposition: attachement; filename="' . $file . '"'); print $firma; exit; }
/** * Acción que entrega el logo del contribuyente * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-29 */ public function logo($rut) { $Contribuyente = new Model_Contribuyente(substr($rut, 0, -4)); if (!$Contribuyente->exists()) { \sowerphp\core\Model_Datasource_Session::message('Contribuyente solicitado no existe'); $this->redirect('/'); } $dir = \sowerphp\core\Configure::read('dte.logos.dir'); $logo = $dir . '/' . $Contribuyente->rut . '.png'; if (!is_readable($logo)) { $logo = $dir . '/default.png'; } header('Content-Type: image/png'); header('Content-Length: ' . filesize($logo)); header('Content-Disposition: inline; filename="' . $Contribuyente->rut . '.png"'); print file_get_contents($logo); exit; }
/** * Método que se ejecuta al terminar la ejecución del controlador * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]delaf.cl) * @version 2014-09-19 */ public function afterFilter() { if ($this->redirect !== null) { if (!is_array($this->redirect)) { $this->redirect($this->redirect); } else { if (isset($this->redirect['msg'])) { \sowerphp\core\Model_Datasource_Session::message($this->redirect['msg']); } $this->redirect($this->redirect['page']); } } if ($this->Components) { $this->Components->trigger('afterFilter'); } }
/** * Método que permite generar un libro de guías de despacho a partir de un * archivo CSV con el detalle del mismo * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-24 */ public function generar_libro_guia() { // si no se viene por post terminar if (!isset($_POST['submit'])) { return; } // verificar campos no estén vacíos $campos = ['RutEmisorLibro', 'PeriodoTributario', 'FchResol', 'NroResol', 'TipoLibro', 'TipoEnvio', 'FolioNotificacion', 'contrasenia']; foreach ($campos as $campo) { if (!isset($_POST[$campo][0])) { \sowerphp\core\Model_Datasource_Session::message($campo . ' no puede estar en blanco', 'error'); return; } } // si no se pasó el archivo error if (!isset($_FILES['archivo']) or $_FILES['archivo']['error']) { \sowerphp\core\Model_Datasource_Session::message('Debes enviar el archivo CSV con el detalle de las guías a la que deseas generar su XML', 'error'); return; } // si no se pasó la firma error if (!isset($_FILES['firma']) or $_FILES['firma']['error']) { \sowerphp\core\Model_Datasource_Session::message('Debes enviar el archivo con la firma digital', 'error'); return; } // Objeto de la Firma try { $Firma = new \sasco\LibreDTE\FirmaElectronica(['data' => file_get_contents($_FILES['firma']['tmp_name']), 'pass' => $_POST['contrasenia']]); } catch (\Exception $e) { \sowerphp\core\Model_Datasource_Session::message('No fue posible abrir la firma digital, quizás contraseña incorrecta', 'error'); return; } // generar caratula del libro $caratula = ['RutEmisorLibro' => str_replace('.', '', $_POST['RutEmisorLibro']), 'PeriodoTributario' => $_POST['PeriodoTributario'], 'FchResol' => $_POST['FchResol'], 'NroResol' => $_POST['NroResol'], 'TipoLibro' => $_POST['TipoLibro'], 'TipoEnvio' => $_POST['TipoEnvio'], 'FolioNotificacion' => $_POST['FolioNotificacion']]; // generar libro de guías $LibroGuia = new \sasco\LibreDTE\Sii\LibroGuia(); $LibroGuia->agregarCSV($_FILES['archivo']['tmp_name']); $LibroGuia->setFirma($Firma); $LibroGuia->setCaratula($caratula); $xml = $LibroGuia->generar(); if (!$LibroGuia->schemaValidate()) { \sowerphp\core\Model_Datasource_Session::message(implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error'); return; } // descargar XML $file = TMP . '/' . $LibroGuia->getID() . '.xml'; file_put_contents($file, $xml); \sasco\LibreDTE\File::compress($file, ['format' => 'zip', 'delete' => true]); exit; }
define('DIR_WEBSITE', DIR_PROJECT . '/website'); // Iniciar buffer ob_start(); // Incluir archivo de funciones básicas y clase para autoload include DIR_FRAMEWORK . '/lib/sowerphp/core/basics.php'; include DIR_FRAMEWORK . '/lib/sowerphp/core/App.php'; // Asociar el método que cargará las clases spl_autoload_register('\\sowerphp\\core\\App::loadClass'); // Crear capas de la aplicación (se registrarán extensiones) \sowerphp\core\App::createLayers($_EXTENSIONS); unset($_EXTENSIONS); // Definir si la aplicación se ejecuta en ambiente de desarrollo // Si estamos en Apache se debe definir en /etc/httpd/conf/httpd.conf: // SetEnv APPLICATION_ENV "dev". // Si estamos en una terminal se debe pasar el flas: --dev global $argv; if (isset($_SERVER['APPLICATION_ENV']) and $_SERVER['APPLICATION_ENV'] == 'dev') { define('ENVIRONMENT_DEV', true); } else { if (is_array($argv) and in_array('--dev', $argv)) { define('ENVIRONMENT_DEV', true); // se quita flasg --dev de los argumentos unset($argv[array_search('--dev', $argv)]); } } // Iniciar sesión y configurar el sitio \sowerphp\core\Configure::bootstrap(); \sowerphp\core\Model_Datasource_Session::start(\sowerphp\core\Configure::read('session.expires')); \sowerphp\core\Model_Datasource_Session::configure(); // autocarga de composer require 'Vendor/autoload.php';
/** * Acción que envía el archivo XML del libro de ventas al SII * Si no hay documentos en el período se enviará sin movimientos * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-12-27 */ public function enviar_sii($periodo) { $Emisor = $this->getContribuyente(); // si el periodo es mayor o igual al actual no se puede enviar if ($periodo >= date('Ym')) { \sowerphp\core\Model_Datasource_Session::message('No puede enviar el libro de ventas del período ' . $periodo . ', debe esperar al mes siguiente del período', 'error'); $this->redirect(str_replace('enviar_sii', 'ver', $this->request->request)); } // obtener ventas $ventas = $Emisor->getVentas($periodo); // crear libro $Libro = new \sasco\LibreDTE\Sii\LibroCompraVenta(); // obtener firma $Firma = $Emisor->getFirma($this->Auth->User->id); if (!$Firma) { \sowerphp\core\Model_Datasource_Session::message('No hay firma electrónica asociada a la empresa (o bien no se pudo cargar), debe agregar su firma antes de generar DTE', 'error'); $this->redirect('/dte/admin/firma_electronicas'); } // agregar detalle $documentos = 0; foreach ($ventas as $venta) { $documentos++; // armar detalle para agregar al libro $d = []; foreach ($venta as $k => $v) { if (strpos($k, 'impuesto_') !== 0) { if ($v !== null) { $d[$this->libro_cols[$k]] = $v; } } } // agregar otros impuestos if (!empty($venta['impuesto_codigo'])) { $d['OtrosImp'] = ['CodImp' => $venta['impuesto_codigo'], 'TasaImp' => $venta['impuesto_tasa'], 'MntImp' => $venta['impuesto_monto']]; } // agregar detalle al libro $Libro->agregar($d); } // agregar carátula al libro $Libro->setCaratula(['RutEmisorLibro' => $Emisor->rut . '-' . $Emisor->dv, 'RutEnvia' => $Firma->getID(), 'PeriodoTributario' => substr($periodo, 0, 4) . '-' . substr($periodo, 4), 'FchResol' => $Emisor->certificacion ? $Emisor->certificacion_resolucion : $Emisor->resolucion_fecha, 'NroResol' => $Emisor->certificacion ? 0 : $Emisor->resolucion_numero, 'TipoOperacion' => 'VENTA', 'TipoLibro' => 'MENSUAL', 'TipoEnvio' => 'TOTAL']); // obtener XML $Libro->setFirma($Firma); $xml = $Libro->generar(); if (!$xml) { \sowerphp\core\Model_Datasource_Session::message('No fue posible generar el libro de ventas<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error'); $this->redirect(str_replace('enviar_sii', 'ver', $this->request->request)); } // enviar al SII $track_id = $Libro->enviar(); if (!$track_id) { \sowerphp\core\Model_Datasource_Session::message('No fue posible enviar el libro de ventas al SII<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error'); $this->redirect(str_replace('enviar_sii', 'ver', $this->request->request)); } // guardar libro de ventas $DteVenta = new Model_DteVenta($Emisor->rut, $periodo, (int) $Emisor->certificacion); $DteVenta->documentos = $documentos; $DteVenta->xml = base64_encode($xml); $DteVenta->track_id = $track_id; $DteVenta->save(); \sowerphp\core\Model_Datasource_Session::message('Libro de ventas período ' . $periodo . ' envíado', 'ok'); $this->redirect(str_replace('enviar_sii', 'ver', $this->request->request)); }
// menú de módulos si hay sesión iniciada if ($_Auth->logged() and $_module_breadcrumb) { echo '<ol class="breadcrumb">', "\n"; $url = '/'; foreach ($_module_breadcrumb as $link => &$name) { if (is_string($link)) { echo ' <li><a href="', $_base, $url, $link, '">', $name, '</a></li>', "\n"; $url .= $link . '/'; } else { echo ' <li class="active">', $name, '</li>'; } } echo '</ol>', "\n"; } // mensaje de sesión $message = \sowerphp\core\Model_Datasource_Session::message(); if ($message) { $icons = ['success' => 'ok', 'info' => 'info-sign', 'warning' => 'warning-sign', 'danger' => 'exclamation-sign']; echo '<div class="alert alert-', $message['type'], '" role="alert">', "\n"; echo ' <span class="glyphicon glyphicon-', $icons[$message['type']], '" aria-hidden="true"></span>', "\n"; echo ' <span class="sr-only">', $message['type'], ': </span>', $message['text'], "\n"; echo '</div>' . "\n"; } // contenido de la página echo $_content; ?> <!-- END MAIN CONTENT --> <div class="center" id="google" style="margin: 2em 0"> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-3829973028217596" data-ad-slot="3431080345" data-ad-format="auto"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script>
/** * Acción que entrega los XML del resultado de la revisión del intercambio * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl) * @version 2015-09-28 */ public function resultados_xml($codigo) { $Emisor = $this->getContribuyente(); // obtener DTE emitido $DteIntercambio = new Model_DteIntercambio($Emisor->rut, $codigo, (int) $Emisor->certificacion); if (!$DteIntercambio->exists()) { \sowerphp\core\Model_Datasource_Session::message('No existe el intercambio solicitado', 'error'); $this->redirect('/dte/dte_intercambios'); } // si no hay XML error if (!$DteIntercambio->recepcion_xml and !$DteIntercambio->recibos_xml and !$DteIntercambio->resultado_xml) { \sowerphp\core\Model_Datasource_Session::message('No existen archivos de resultado generados, no se ha procesado aun el intercambio', 'error'); $this->redirect(str_replace('resultados_xml', 'ver', $this->request->request)); } // agregar a archivo comprimido y entregar $dir = TMP . '/resultado_intercambio_' . $Emisor->rut . '-' . $Emisor->dv . '_' . $DteIntercambio->codigo; if (is_dir($dir)) { \sowerphp\general\Utility_File::rmdir($dir); } if (!mkdir($dir)) { \sowerphp\core\Model_Datasource_Session::message('No fue posible crear el directorio temporal para los XML', 'error'); $this->redirect(str_replace('resultados_xml', 'ver', $this->request->request)); } if ($DteIntercambio->recepcion_xml) { file_put_contents($dir . '/RecepcionDTE.xml', base64_decode($DteIntercambio->recepcion_xml)); } if ($DteIntercambio->recibos_xml) { file_put_contents($dir . '/EnvioRecibos.xml', base64_decode($DteIntercambio->recibos_xml)); } if ($DteIntercambio->resultado_xml) { file_put_contents($dir . '/ResultadoDTE.xml', base64_decode($DteIntercambio->resultado_xml)); } \sowerphp\general\Utility_File::compress($dir, ['format' => 'zip', 'delete' => true]); exit; }