Merge branch 'pdf_factura' into 'main'

Pdf factura

See merge request jjimenez/safekat!306
This commit is contained in:
Ignacio Martinez Navajas
2024-08-17 17:17:36 +00:00
10 changed files with 841 additions and 21 deletions

View File

@ -700,6 +700,15 @@ $routes->group(
}
);
$routes->group(
'print-factura',
['namespace' => 'App\Controllers\Pdf'],
function ($routes) {
$routes->get('index/(:num)', 'PrintFacturas::index/$1', ['as' => 'viewFacturaPDF']);
$routes->get('generar/(:num)', 'PrintFacturas::generar/$1', ['as' => 'facturaToPdf']);
}
);
$routes->group(
'export-giros',
['namespace' => 'App\Controllers\Excel'],
@ -708,6 +717,14 @@ $routes->group(
}
);
$routes->group(
'export-lineas',
['namespace' => 'App\Controllers\Excel'],
function ($routes) {
$routes->get('generar/(:num)', 'PrintLineas::generateExcel/$1', ['as' => 'lineasToExcel']);
}
);
$routes->group(
'buscadorpresupuestos',
['namespace' => 'App\Controllers\Presupuestos'],

View File

@ -0,0 +1,70 @@
<?php
namespace App\Controllers\Excel;
use App\Controllers\BaseController;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
class PrintLineas extends BaseController
{
public function generateExcel($factura_id = null)
{
// Modelos
$lineasFacturaModel = model('App\Models\Facturas\FacturaLineaModel');
$infoLineasFactura = $lineasFacturaModel->getResourceForExcel($factura_id)->get()->getResultObject();
// Crear un nuevo Spreadsheet
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// Especificar encabezados
$headers = [
'Factura',
'ID Pedido',
'Ref. Cliente',
'Base'
];
// Establecer los encabezados en la primera fila
$column = 'A';
foreach ($headers as $header) {
$sheet->setCellValue($column . '1', $header);
$column++;
}
// Rellenar las filas con datos
$rowNumber = 2; // Empezar en la segunda fila
foreach ($infoLineasFactura as $infoLineaFactura) {
$column = 'A';
foreach ($infoLineaFactura as $cell) {
$sheet->setCellValue($column . $rowNumber, $cell);
$column++;
}
$rowNumber++;
}
// Ajustar automáticamente el tamaño de las columnas
foreach (range('A', $column) as $col) {
$sheet->getColumnDimension($col)->setAutoSize(true);
}
// Crear un escritor para guardar el archivo
$writer = new Xlsx($spreadsheet);
// Configurar la respuesta para descarga
$fileName = 'lineas-pedido.xlsx';
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="' . $fileName . '"');
header('Cache-Control: max-age=0');
// Escribir el archivo a la salida
$writer->save('php://output');
exit;
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace App\Controllers\Pdf;
use App\Controllers\BaseController;
class PrintFacturas extends BaseController
{
public function index($id_factura)
{
$facturaModel = model('App\Models\Facturas\FacturaModel');
$lineasFacturaModel = model('App\Models\Facturas\FacturaLineaModel');
$data['factura'] = $facturaModel->getResourceForPdf($id_factura)->get()->getRow();
$data['lineas_factura'] = $lineasFacturaModel->getResourceForPdf($id_factura)->get()->getResultObject();
$data['resumen_por_iva'] = $lineasFacturaModel->getResourceResumenIVAsForPdf($id_factura)->get()->getResultObject();
return view(getenv('theme.path') . 'pdfs/factura', $data);
}
public function generar($id_factura)
{
// Cargar modelos
$facturaModel = model('App\Models\Facturas\FacturaModel');
$lineasFacturaModel = model('App\Models\Facturas\FacturaLineaModel');
// Informacion del presupuesto
$data['factura'] = $facturaModel->getResourceForPdf($id_factura)->get()->getRow();
$data['lineas_factura'] = $lineasFacturaModel->getResourceForPdf($id_factura)->get()->getResultObject();
$data['resumen_por_iva'] = $lineasFacturaModel->getResourceResumenIVAsForPdf($id_factura)->get()->getResultObject();
// Crear una instancia de Dompdf
$options = new \Dompdf\Options();
$options->set('isHtml5ParserEnabled', true);
$options->set('isPhpEnabled', true);
$options->set('isRemoteEnabled', true);
$dompdf = new \Dompdf\Dompdf($options);
// Contenido HTML del documento
$dompdf->loadHtml(view(getenv('theme.path').'pdfs/factura', $data));
// Establecer el tamaño del papel
$dompdf->setPaper('A4', 'portrait');
// Renderizar el PDF
$dompdf->render();
// Obtener el contenido generado
$output = $dompdf->output();
// Establecer las cabeceras para visualizar en lugar de descargar
$file_name = $data['factura']->numero . ".pdf";
return $this->response
->setStatusCode(200)
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'inline; filename="' . $file_name . '"')
->setHeader('Cache-Control', 'private, max-age=0, must-revalidate')
->setHeader('Pragma', 'public')
->setHeader('Content-Length', strlen($output))
->setBody($output);
}
}

View File

@ -54,6 +54,76 @@ class FacturaLineaModel extends \App\Models\BaseModel {
return $builder;
}
public function getResourceResumenIVAsForPdf($factura_id = -1)
{
$builder = $this->db
->table($this->table . " t1")
->select(
"t1.iva,
ROUND(SUM(t1.base), 2) AS base,
ROUND(SUM(t1.total_iva), 2) AS total_iva,
ROUND(SUM(t1.total), 2) AS total"
)
->where("t1.factura_id", $factura_id)
->where("t1.deleted_at", null)
->groupBy('t1.iva')
->orderBy('t1.iva', 'ASC'); // Ordena por iva en forma ascendente
return $builder;
}
/**
* Get resource data for creating PDFs.
*
* @param string $search
*
* @return \CodeIgniter\Database\BaseBuilder
*/
public function getResourceForPdf($factura_id = -1)
{
$builder = $this->db
->table($this->table . " t1")
->select(
"t1.id AS id, t1.factura_id AS factura_id,
t1.pedido_linea_impresion_id AS pedido_linea_impresion_id, t1.pedido_maquetacion_id AS pedido_maquetacion_id,
t1.descripcion AS descripcion, t1.cantidad as cantidad, t1.precio_unidad AS precio_unidad, t1.iva AS iva,
t1.base AS base, t1.total_iva AS total_iva, t1.total AS total, t1.data AS data"
)
->where("t1.factura_id", $factura_id)
->where("t1.deleted_at", null);
return $builder;
}
/**
* Get resource data for creating PDFs.
*
* @param string $search
*
* @return \CodeIgniter\Database\BaseBuilder
*/
public function getResourceForExcel($factura_id = -1)
{
$builder = $this->db
->table($this->table . " t1")
->select(
"t2.numero AS ref_factura,
t3.pedido_id AS pedido_id,
t4.referencia_cliente AS referencia_cliente,
t1.base AS base"
)
->join("facturas t2", "t2.id = t1.factura_id", "left")
->join("pedidos_linea t3", "t3.id = t1.pedido_linea_impresion_id", "left")
->join("presupuestos t4", "t4.id = t3.presupuesto_id", "left")
->where("t1.factura_id", $factura_id)
->where("t1.deleted_at", null);
return $builder;
}
public function addFacturaPedidoLinea($factura_id, $pedido_linea_id, $cantidad)
{
$data = [

View File

@ -102,6 +102,41 @@ class FacturaModel extends \App\Models\BaseModel {
}
/**
* Get resource data for creating PDFs.
*
* @param string $search
*
* @return \CodeIgniter\Database\BaseBuilder
*/
public function getResourceForPdf($factura_id = -1)
{
$builder = $this->db
->table($this->table . " t1")
->select(
"t1.id AS id, t1.numero AS numero, DATE_FORMAT(t1.fecha_factura_at, '%d/%m/%Y') AS fecha_factura_at,
t1.base AS base, t1.total AS total, t1.pendiente AS pendiente,
t1.creditoAsegurado AS creditoAsegurado, t1.estado AS estado, t1.estado_pago AS estado_pago,
t4.nombre AS forma_pago,
DATE_FORMAT(MIN(CASE WHEN t3.fecha_vencimiento_at != '0000-00-00 00:00:00' THEN t3.fecha_vencimiento_at ELSE NULL END), '%d/%m/%Y') AS vencimiento,
t2.nombre AS cliente, t2.direccion AS cliente_direccion, t2.ciudad AS cliente_ciudad,
t2.cp AS cliente_cp, t2.cif AS cliente_cif, t2.vencimiento AS dias_vencimiento, t2.ccc AS cliente_ccc,
t5.nombre AS cliente_pais"
);
$builder->join("clientes t2", "t2.id = t1.cliente_id", "left");
$builder->join("facturas_pagos t3", "t3.factura_id = t1.id", "left");
$builder->join("formas_pago t4", "t3.forma_pago_id = t4.id", "left");
$builder->join("lg_paises t5", "t2.pais_id = t5.id", "left");
$builder->where("t1.id", $factura_id);
$builder->where("t1.deleted_at IS NULL");
$builder->groupBy("t1.id"); // Agrupa por id de la factura
return $builder;
}
public function getResourcePedidos($pedido_id)
{
$builder = $this->db

View File

@ -191,15 +191,15 @@
<?= lang("Basic.global.edit") ?>
</button>
<?php endif; ?>
<button
type="button"
class="btn btn-label-primary float-start me-sm-3 me-1"
name="exportar_lineas"
id="exportar_lineas" >
<span class="ti-xs ti ti-file-spreadsheet me-1"></span>
<?= lang("Facturas.exportarLineas") ?>
</button>
<?= anchor(
route_to("lineasToExcel", $facturaEntity->id),
'<span class="ti-xs ti ti-file-spreadsheet me-1"></span>' .
lang("Facturas.exportarLineas"),
[
"class" => "btn btn-label-primary float-start me-sm-3 me-1",
]
) ?>
<button
type="button"

View File

@ -44,13 +44,21 @@
value="<?= lang("Facturas.borrarFactura") ?>"
/>
<?php endif; ?>
<input type="button"
class="btn btn-info float-start me-sm-3 me-1"
id="imprimirFactura"
name="imprimirFactura"
value="<?= lang("Facturas.imprimirFactura") ?>"
/>
<?= anchor(route_to("facturasList"), lang("Basic.global.back"), ["class" => "btn btn-secondary float-start"]) ?>
<?= anchor(
route_to("facturaToPdf", $facturaEntity->id),
lang("Facturas.imprimirFactura"),
[
"class" => "btn btn-info float-start me-sm-3 me-1",
"target" => "_blank"
]
) ?>
<?= anchor(
route_to("facturasList"),
lang("Basic.global.back"),
[
"class" => "btn btn-secondary float-start"
]
) ?>
</div><!-- /.card-footer -->
</form>
</div><!-- //.card -->

View File

@ -78,11 +78,60 @@
pageLength: 250,
lengthChange: true,
"dom": 'lfBrtip',
"buttons": [
'copy', 'csv', 'excel', 'print', {
extend: 'pdfHtml5',
orientation: 'landscape',
pageSize: 'A4'
buttons: [
{
text: 'Exportar Excel Contaplus',
action: function (e, dt, button, config) {
var searchValue = theTable.search(); // Captura el valor del campo de búsqueda
var ajaxParams = theTable.ajax.params(); // Captura otros parámetros de la tabla
console.log(searchValue);
/*
$.ajax({
url: '/ruta/exportarExcel', // URL del servidor para manejar la exportación
type: 'POST',
data: {
search: searchValue,
extraParams: ajaxParams
},
xhrFields: {
responseType: 'blob' // Para manejar la descarga del archivo
},
success: function(blob, status, xhr) {
// Crear un enlace temporal para descargar el archivo
var link = document.createElement('a');
var url = window.URL.createObjectURL(blob);
link.href = url;
link.download = 'datos_personalizados.xlsx';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}
});
*/
}
},
{
text: 'Exportar Lineas a Excel',
action: function (e, dt, button, config) {
var searchValue = theTable.search(); // Captura el valor del campo de búsqueda
var ajaxParams = theTable.ajax.params(); // Captura otros parámetros de la tabla
console.log(searchValue);
}
},
{
text: 'Exportar Girosgit ',
action: function (e, dt, button, config) {
var searchValue = theTable.search(); // Captura el valor del campo de búsqueda
var ajaxParams = theTable.ajax.params(); // Captura otros parámetros de la tabla
console.log(searchValue);
}
}
],
stateSave: true,

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,313 @@
/* Facturas Safekat */
* {
box-sizing: border-box;
}
body {
font-family: 'Open Sans', sans-serif;
font-size: 14px;
line-height: 1.42857143;
color: #333;
background-color: #fff;
}
table {
border-spacing: 0;
background-color: transparent;
border-collapse: collapse;
}
th {
text-align: left;
}
td {
padding: 0;
}
body table.logo {
padding: 0;
width: 100%;
color: black;
}
body table.logo td.logo img {
width: 100%;
vertical-align: middle;
}
/* Estilos intro-factura */
body table.intro-factura {
width: 100%;
font-size: 12px;
margin-top: -22px;
}
body table.intro-factura th {
background: black;
color: white;
padding: 7px;
}
body table.intro-factura th.intro_num_factura {
width: 20%;
padding-left: 15px;
}
body table.intro-factura th.num_factura {
width: 47%;
font-weight: lighter;
text-align: left;
}
body table.intro-factura th.intro_fecha {
width: 17%;
text-align: right;
}
body table.intro-factura th.fecha {
width: 15%;
text-align: right;
font-weight: lighter;
}
body table.intro-factura td {
background: #e3e4e7;
padding-left: 15px;
color: black;
font-size: 12px;
}
body table.intro-factura td.intro_direccion {
padding-top: 10px;
padding-right: 8px;
font-weight: bold;
}
body table.intro-factura td.direccion {
padding-right: 8px;
}
/* Estilos cuerpo factura */
div.cuerpo-factura {
margin-bottom: 25px;
}
table.factura-data-superior {
width: 100%;
}
table.factura-data-superior th {
padding: 5px !important;
background: #0C2C84;
color: white;
padding-left: 10px;
font-weight: lighter;
font-size: 12px;
border-right: 1px solid white;
}
table.factura-data-superior td {
border: 1px dotted #4e4e4e;
border-top: none;
padding: 5px !important;
text-align: right;
font-size: 11px;
}
table.factura-data-superior td.tipo_trabajo {
border-left: none;
text-align: left;
}
table.factura-data-superior td.subtotal {
border-right: none;
}
/* Estilos para el sello de Solunion */
.sello-solunion {
float: left; /* Hace que el sello flote a la izquierda */
margin-left: 100px; /* Espacio entre el sello y la tabla */
}
.sello-solunion img {
display: block; /* Asegura que la imagen se comporte como un bloque dentro del div */
width: 80px; /* Ajusta el tamaño de la imagen según sea necesario */
height: auto;
}
/* Contenedor para manejar el flujo de contenido */
.container {
overflow: hidden; /* Asegura que el contenedor se ajuste al contenido flotante */
}
/* Estilos para la tabla de precios inferior */
table.factura-precio-inferior {
width: 60%; /* Ajusta el ancho de la tabla al 100% del contenedor */
text-align: right;
border-collapse: collapse; /* Asegura que los bordes se colapsen para evitar espacio extra */
margin-bottom: 0; /* Elimina el margen inferior para evitar espacio extra */
}
table.factura-precio-inferior th, table.factura-precio-inferior td {
padding: 5px;
border-bottom: 1px dotted #4e4e4e;
}
table.factura-precio-inferior th.intro_base,
table.factura-precio-inferior th.intro_iva,
table.factura-precio-inferior th.intro_total {
background: #0C2C84;
color: white;
font-size: 12px;
}
table.factura-precio-inferior td.base,
table.factura-precio-inferior td.iva,
table.factura-precio-inferior td.value_iva,
table.factura-precio-inferior td.total {
font-size: 11px;
}
/* Estilos para la tabla de totales */
table.totales {
width: 28%; /* Ajusta el ancho de la tabla según sea necesario */
background: #0C2C84;
color: white;
font-size: 12px;
border-collapse: collapse; /* Asegura que los bordes se colapsen para evitar espacio extra */
margin-top: 0; /* Elimina el margen superior para evitar espacio extra */
margin-bottom: 0; /* Elimina el margen inferior para evitar espacio extra */
}
table.totales td.intro_total_factura {
width: 20%;
text-align: right;
padding: 5px;
}
table.totales td.total_factura {
width: 15%;
text-align: right;
padding-right: 10px;
}
/* Estilos factura-data-inferior-iva */
table.factura-data-inferior-iva {
width: 100%;
margin-top: 8px;
}
table.factura-data-inferior-iva th {
padding: 5px !important;
background: rgb(233, 240, 255);
font-weight: lighter;
font-size: 12px;
padding-left: 7px;
color: black;
border-right: 1px solid white;
}
table.factura-data-inferior-iva th.intro_vencimiento,
table.factura-data-inferior-iva th.inferior_intro_fecha {
width: 15%;
}
table.factura-data-inferior-iva th.intro_forma_pago {
width: 20%;
}
table.factura-data-inferior-iva th.intro_bic {
width: 50%;
}
table.factura-data-inferior-iva td {
border-bottom: 1px dotted #4e4e4e;
border-top: none;
padding-left: 8px;
padding: 3px !important;
font-size: 11px;
}
table.factura-data-inferior-iva td.vencimiento,
table.factura-data-inferior-iva td.inferior_fecha,
table.factura-data-inferior-iva td.forma_pago {
border-right: 1px dotted black;
}
/* Estilos factura-precio-inferior */
table.factura-data-inferior {
width: 100%;
background: #e3e4e7;
font-size: 12px;
margin-top: 5px;
}
table.factura-data-inferior th {
padding-top: 2px;
font-weight: lighter;
}
table.factura-data-inferior th.intro_vencimiento,
table.factura-data-inferior th.intro_base,
table.factura-data-inferior th.base {
padding-top: 8px;
}
table.factura-data-inferior th.intro_vencimiento,
table.factura-data-inferior th.inferior_intro_fecha,
table.factura-data-inferior th.intro_forma_pago,
table.factura-data-inferior th.intro_bic {
font-weight: bold;
padding-left: 10px;
}
table.factura-data-inferior th.intro_base,
table.factura-data-inferior th.intro_value_iva,
table.factura-data-inferior th.intro_iva,
table.factura-data-inferior th.intro_total {
color: #0C2C84;
text-align: right;
padding-right: 5px;
}
table.factura-data-inferior th.base,
table.factura-data-inferior th.iva,
table.factura-data-inferior th.value_iva,
table.factura-data-inferior th.total {
border-left: 1px dashed grey;
text-align: right;
padding-right: 10px;
width: 15%;
}
table.factura-data-inferior th.intro_bic,
table.factura-data-inferior th.intro_total,
table.factura-data-inferior th.total {
padding-bottom: 8px;
}
/* Estilos para el pie de página */
.footer {
width: 95%;
position: fixed; /* Fija el pie de página en la parte inferior */
bottom: 15px; /* Coloca el pie de página en la parte inferior de la página */
}
/* Estilos pie */
div.pie {
font-family: sans-serif;
font-size: 7px;
margin: 5mm 0 5mm 0;
}
/* Estilos pie-pagina */
table.pie-pagina {
font-family: sans-serif;
color: #0C2C84;
float: left;
vertical-align: bottom;
font-size: 10px;
font-weight: bold;
}