mirror of
https://git.imnavajas.es/jjimenez/safekat.git
synced 2025-07-25 22:52:08 +00:00
Preparada factura en PDF
This commit is contained in:
@ -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'],
|
||||
|
||||
65
ci4/app/Controllers/Pdf/PrintFacturas.php
Normal file
65
ci4/app/Controllers/Pdf/PrintFacturas.php
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -54,6 +54,56 @@ 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)
|
||||
->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, t2.pedido_id AS pedido_id,
|
||||
t3.total_aceptado AS total_aceptado, t4.tirada_flexible AS tirada_flexible, t4.descuento_tirada_flexible AS descuento_tirada_flexible,
|
||||
t6.cantidad AS cantidad_albaran"
|
||||
)
|
||||
->join("pedidos_linea t2", "t2.id = t1.pedido_linea_impresion_id", "left")
|
||||
->join("presupuestos t3", "t3.id = t2.presupuesto_id", "left")
|
||||
->join("clientes t4", "t4.id = t3.cliente_id", "left")
|
||||
->join("albaranes t5", "t5.pedido_id = t2.pedido_id", "left")
|
||||
->join("albaranes_lineas t6", "t6.albaran_id = t5.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 = [
|
||||
|
||||
@ -102,6 +102,40 @@ 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.deleted_at IS NULL");
|
||||
$builder->groupBy("t1.id"); // Agrupa por id de la factura
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
|
||||
public function getResourcePedidos($pedido_id)
|
||||
{
|
||||
$builder = $this->db
|
||||
|
||||
193
ci4/app/Views/themes/vuexy/pdfs/factura.php
Normal file
193
ci4/app/Views/themes/vuexy/pdfs/factura.php
Normal file
File diff suppressed because one or more lines are too long
313
httpdocs/themes/vuexy/css/pdf.factura.css
Normal file
313
httpdocs/themes/vuexy/css/pdf.factura.css
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user