Ejemplo n.º 1
0
 /**
  * Acción que permite importar un libro desde un archivo CSV
  * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
  * @version 2015-12-29
  */
 public function importar()
 {
     if (isset($_POST['submit'])) {
         // verificar que se haya podido subir el archivo con el libro
         if (!isset($_FILES['archivo']) or $_FILES['archivo']['error']) {
             \sowerphp\core\Model_Datasource_Session::message('Ocurrió un error al subir el libro', 'error');
             return;
         }
         // obtener receptor (contribuyente operando)
         $Receptor = $this->getContribuyente();
         $Libro = new \sasco\LibreDTE\Sii\LibroCompraVenta();
         $Libro->agregarComprasCSV($_FILES['archivo']['tmp_name']);
         $detalle = $Libro->getCompras();
         // agregar cada documento del libro
         $keys = array_keys($this->detalle_cols);
         $noGuardado = [];
         foreach ($detalle as $d) {
             $datos = array_combine($keys, $d);
             $DteRecibido = new Model_DteRecibido();
             $DteRecibido->set($datos);
             $DteRecibido->emisor = explode('-', str_replace('.', '', $datos['rut']))[0];
             $DteRecibido->certificacion = $Receptor->certificacion;
             $DteRecibido->receptor = $Receptor->rut;
             $DteRecibido->usuario = $this->Auth->User->id;
             try {
                 if (!$DteRecibido->save()) {
                     $noGuardado[] = 'T' . $DteRecibido->dte . 'F' . $DteRecibido->folio;
                 }
             } catch (\sowerphp\core\Exception_Model_Datasource_Database $e) {
                 $noGuardado[] = 'T' . $DteRecibido->dte . 'F' . $DteRecibido->folio . ': ' . $e->getMessage();
             }
         }
         // mostrar errores o redireccionar
         if ($noGuardado) {
             \sowerphp\core\Model_Datasource_Session::message('Los siguientes documentos no se agregaron:<br/><br/>- ' . implode('<br/><br/>- ', $noGuardado), 'error');
         } else {
             \sowerphp\core\Model_Datasource_Session::message('Se importó el libro de compras', 'ok');
             $this->redirect('/dte/dte_compras');
         }
     }
 }
 /**
  * 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');
     }
 }
 /**
  * Acción que procesa y responde al intercambio recibido
  * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
  * @version 2015-10-08
  */
 public function responder($codigo)
 {
     $Emisor = $this->getContribuyente();
     // si no se viene por post error
     if (!isset($_POST['submit'])) {
         \sowerphp\core\Model_Datasource_Session::message('No puede acceder de forma directa a ' . $this->request->request, 'error');
         $this->redirect(str_replace('responder', 'ver', $this->request->request));
     }
     // 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');
     }
     // 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');
     }
     //
     // construir RecepcionDTE
     //
     $RecepcionDTE = [];
     $n_dtes = count($_POST['TipoDTE']);
     for ($i = 0; $i < $n_dtes; $i++) {
         $RecepcionDTE[] = ['TipoDTE' => $_POST['TipoDTE'][$i], 'Folio' => $_POST['Folio'][$i], 'FchEmis' => $_POST['FchEmis'][$i], 'RUTEmisor' => $_POST['RUTEmisor'][$i], 'RUTRecep' => $_POST['RUTRecep'][$i], 'MntTotal' => $_POST['MntTotal'][$i], 'EstadoRecepDTE' => $_POST['EstadoRecepDTE'][$i], 'RecepDTEGlosa' => $_POST['RecepDTEGlosa'][$i]];
     }
     // armar respuesta de envío
     $EnvioDte = new \sasco\LibreDTE\Sii\EnvioDte();
     $EnvioDte->loadXML(base64_decode($DteIntercambio->archivo_xml));
     $Caratula = $EnvioDte->getCaratula();
     $RespuestaEnvio = new \sasco\LibreDTE\Sii\RespuestaEnvio();
     $RespuestaEnvio->agregarRespuestaEnvio(['NmbEnvio' => $DteIntercambio->archivo, 'CodEnvio' => $DteIntercambio->codigo, 'EnvioDTEID' => $EnvioDte->getID(), 'Digest' => $EnvioDte->getDigest(), 'RutEmisor' => $EnvioDte->getEmisor(), 'RutReceptor' => $EnvioDte->getReceptor(), 'EstadoRecepEnv' => $_POST['EstadoRecepEnv'], 'RecepEnvGlosa' => $_POST['RecepEnvGlosa'], 'NroDTE' => count($RecepcionDTE), 'RecepcionDTE' => $RecepcionDTE]);
     // asignar carátula y Firma
     $RespuestaEnvio->setCaratula(['RutResponde' => $Emisor->rut . '-' . $Emisor->dv, 'RutRecibe' => $Caratula['RutEmisor'], 'IdRespuesta' => $DteIntercambio->codigo, 'NmbContacto' => $_POST['NmbContacto'], 'MailContacto' => $_POST['MailContacto']]);
     $RespuestaEnvio->setFirma($Firma);
     // generar y validar XML
     $RecepcionDTE_xml = $RespuestaEnvio->generar();
     if (!$RespuestaEnvio->schemaValidate()) {
         \sowerphp\core\Model_Datasource_Session::message('No fue posible generar RecepcionDTE.<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error');
         $this->redirect(str_replace('responder', 'ver', $this->request->request));
     }
     //
     // generar EnvioRecibos
     //
     $EnvioRecibos = new \sasco\LibreDTE\Sii\EnvioRecibos();
     $EnvioRecibos->setCaratula(['RutResponde' => $Emisor->rut . '-' . $Emisor->dv, 'RutRecibe' => $Caratula['RutEmisor'], 'NmbContacto' => $_POST['NmbContacto'], 'MailContacto' => $_POST['MailContacto']]);
     $EnvioRecibos->setFirma($Firma);
     // procesar cada DTE
     $EnvioRecibos_r = [];
     for ($i = 0; $i < $n_dtes; $i++) {
         if ($_POST['acuse'][$i]) {
             $EnvioRecibos->agregar(['TipoDoc' => $_POST['TipoDTE'][$i], 'Folio' => $_POST['Folio'][$i], 'FchEmis' => $_POST['FchEmis'][$i], 'RUTEmisor' => $_POST['RUTEmisor'][$i], 'RUTRecep' => $_POST['RUTRecep'][$i], 'MntTotal' => $_POST['MntTotal'][$i], 'Recinto' => $_POST['Recinto'], 'RutFirma' => $Firma->getID()]);
             $EnvioRecibos_r[] = 'T' . $_POST['TipoDTE'][$i] . 'F' . $_POST['Folio'][$i];
         }
     }
     // generar y validar XML
     if ($EnvioRecibos_r) {
         $EnvioRecibos_xml = $EnvioRecibos->generar();
         if (!$EnvioRecibos->schemaValidate()) {
             \sowerphp\core\Model_Datasource_Session::message('No fue posible generar EnvioRecibos.<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error');
             $this->redirect(str_replace('responder', 'ver', $this->request->request));
         }
     }
     //
     // generar ResultadoDTE
     //
     // objeto para la respuesta
     $RespuestaEnvio = new \sasco\LibreDTE\Sii\RespuestaEnvio();
     // procesar cada DTE
     for ($i = 0; $i < $n_dtes; $i++) {
         $estado = !$_POST['EstadoRecepDTE'][$i] ? 0 : 2;
         $RespuestaEnvio->agregarRespuestaDocumento(['TipoDTE' => $_POST['TipoDTE'][$i], 'Folio' => $_POST['Folio'][$i], 'FchEmis' => $_POST['FchEmis'][$i], 'RUTEmisor' => $_POST['RUTEmisor'][$i], 'RUTRecep' => $_POST['RUTRecep'][$i], 'MntTotal' => $_POST['MntTotal'][$i], 'CodEnvio' => $i + 1, 'EstadoDTE' => $estado, 'EstadoDTEGlosa' => \sasco\LibreDTE\Sii\RespuestaEnvio::$estados['respuesta_documento'][$estado]]);
     }
     // asignar carátula y Firma
     $RespuestaEnvio->setCaratula(['RutResponde' => $Emisor->rut . '-' . $Emisor->dv, 'RutRecibe' => $Caratula['RutEmisor'], 'IdRespuesta' => $DteIntercambio->codigo, 'NmbContacto' => $_POST['NmbContacto'], 'MailContacto' => $_POST['MailContacto']]);
     $RespuestaEnvio->setFirma($Firma);
     // generar y validar XML
     $ResultadoDTE_xml = $RespuestaEnvio->generar();
     if (!$RespuestaEnvio->schemaValidate()) {
         \sowerphp\core\Model_Datasource_Session::message('No fue posible generar ResultadoDTE.<br/>' . implode('<br/>', \sasco\LibreDTE\Log::readAll()), 'error');
         $this->redirect(str_replace('responder', 'ver', $this->request->request));
     }
     //
     // guardar estado del intercambio y usuario que lo procesó
     //
     $DteIntercambio->estado = (int) $_POST['EstadoRecepEnv'];
     $DteIntercambio->recepcion_xml = base64_encode($RecepcionDTE_xml);
     if (isset($EnvioRecibos_xml)) {
         $DteIntercambio->recibos_xml = base64_encode($EnvioRecibos_xml);
     }
     $DteIntercambio->resultado_xml = base64_encode($ResultadoDTE_xml);
     $DteIntercambio->fecha_hora_respuesta = date('Y-m-d H:i:s');
     $DteIntercambio->usuario = $this->Auth->User->id;
     $DteIntercambio->save();
     //
     // guardar documentos que han sido aceptados con acuse de recibo
     //
     if (isset($EnvioRecibos_xml)) {
         // actualizar datos del emisor si no tine usuario asociado
         $EmisorIntercambio = $DteIntercambio->getEmisor();
         if (!$EmisorIntercambio->usuario) {
             $emisor = $DteIntercambio->getDocumentos()[0]->getDatos()['Encabezado']['Emisor'];
             $EmisorIntercambio->razon_social = $emisor['RznSoc'];
             if (!empty($emisor['GiroEmis'])) {
                 $EmisorIntercambio->giro = $emisor['GiroEmis'];
             }
             if (!empty($emisor['CorreoEmisor'])) {
                 $EmisorIntercambio->email = $emisor['CorreoEmisor'];
             }
             if (!empty($emisor['Acteco'])) {
                 $actividad_economica = $EmisorIntercambio->actividad_economica;
                 $EmisorIntercambio->actividad_economica = $emisor['Acteco'];
                 if (!$EmisorIntercambio->getActividadEconomica()->exists()) {
                     $EmisorIntercambio->actividad_economica = $actividad_economica;
                 }
             }
             $comuna = (new \sowerphp\app\Sistema\General\DivisionGeopolitica\Model_Comunas())->getComunaByName($emisor['CmnaOrigen']);
             if ($comuna) {
                 $EmisorIntercambio->direccion = $emisor['DirOrigen'];
                 $EmisorIntercambio->comuna = $comuna;
             }
             if (!empty($emisor['CdgSIISucur'])) {
                 $EmisorIntercambio->sucursal_sii = (int) $emisor['CdgSIISucur'];
             }
             $EmisorIntercambio->modificado = date('Y-m-d H:i:s');
             $EmisorIntercambio->save();
         }
         // guardar documentos que tienen acuse de recibo como dte recibidos
         $Documentos = $DteIntercambio->getDocumentos();
         foreach ($Documentos as $Dte) {
             if (in_array($Dte->getID(), $EnvioRecibos_r)) {
                 $resumen = $Dte->getResumen();
                 $DteRecibido = new Model_DteRecibido();
                 $DteRecibido->emisor = $DteIntercambio->getEmisor()->rut;
                 $DteRecibido->dte = $resumen['TpoDoc'];
                 $DteRecibido->folio = $resumen['NroDoc'];
                 $DteRecibido->certificacion = (int) $DteIntercambio->certificacion;
                 if (!$DteRecibido->exists()) {
                     $DteRecibido->receptor = $Emisor->rut;
                     $DteRecibido->tasa = (int) $resumen['TasaImp'];
                     $DteRecibido->fecha = $resumen['FchDoc'];
                     $DteRecibido->sucursal_sii = (int) $resumen['CdgSIISucur'];
                     if ($resumen['MntExe']) {
                         $DteRecibido->exento = $resumen['MntExe'];
                     }
                     if ($resumen['MntNeto']) {
                         $DteRecibido->neto = $resumen['MntNeto'];
                     }
                     $DteRecibido->iva = (int) $resumen['MntIVA'];
                     $DteRecibido->total = (int) $resumen['MntTotal'];
                     $DteRecibido->usuario = $this->Auth->User->id;
                     $DteRecibido->intercambio = $DteIntercambio->codigo;
                     $DteRecibido->save();
                 }
             }
         }
     }
     //
     // enviar los 3 XML de respuesta por email
     //
     $email = $Emisor->getEmailSmtp();
     $email->to($_POST['responder_a']);
     $email->subject($Emisor->rut . '-' . $Emisor->dv . ' - Respuesta intercambio N° ' . $DteIntercambio->codigo);
     foreach (['RecepcionDTE', 'EnvioRecibos', 'ResultadoDTE'] as $xml) {
         if (isset(${$xml . '_xml'})) {
             $email->attach(['data' => ${$xml . '_xml'}, 'name' => $xml . '_' . $Emisor->rut . '-' . $Emisor->dv . '_' . $DteIntercambio->codigo . '.xml', 'type' => 'application/xml']);
         }
     }
     // enviar email
     $status = $email->send('Se adjuntan XMLs de respuesta a intercambio de DTE.');
     if ($status === true) {
         \sowerphp\core\Model_Datasource_Session::message('Se procesaron DTEs de intercambio y se envió la respuesta a: ' . $_POST['responder_a'], 'ok');
     } else {
         \sowerphp\core\Model_Datasource_Session::message('Se procesaron DTEs de intercambio, pero no fue posible enviar el email, por favor intente nuevamente.<br /><em>' . $status['message'] . '</em>', 'error');
     }
     $this->redirect(str_replace('responder', 'ver', $this->request->request));
 }