mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-02-08 11:59:13 +00:00
terminando pdf de facturas
This commit is contained in:
@ -9,6 +9,8 @@
|
||||
<link th:href="@{/assets/css/presupuestador.css}" rel="stylesheet"
|
||||
th:unless="${#authorization.expression('isAuthenticated()')}" />
|
||||
<link th:href="@{/assets/libs/datatables/dataTables.bootstrap5.min.css}" rel="stylesheet" />
|
||||
<link sec:authorize="isAuthenticated() and hasAnyRole('SUPERADMIN','ADMIN')"
|
||||
th:href="@{/assets/libs/quill/quill.snow.css}" rel="stylesheet" type="text/css" />
|
||||
</th:block>
|
||||
|
||||
</head>
|
||||
@ -68,6 +70,9 @@
|
||||
<script th:src="@{/assets/libs/datatables/buttons.print.min.js}"></script>
|
||||
<script th:src="@{/assets/libs/datatables/buttons.colVis.min.js}"></script>
|
||||
|
||||
<script sec:authorize="isAuthenticated() and hasAnyRole('SUPERADMIN','ADMIN')"
|
||||
th:src="@{/assets/libs/quill/quill.min.js}"></script>
|
||||
|
||||
<script type="module" th:src="@{/assets/js/pages/imprimelibros/facturas/view.js}"></script>
|
||||
|
||||
</th:block>
|
||||
|
||||
@ -15,17 +15,17 @@
|
||||
|
||||
<div class="row g-3">
|
||||
|
||||
<!-- Número -->
|
||||
<!-- Número (solo lectura siempre, normalmente) -->
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" th:text="#{facturas.form.numero-factura}">Número</label>
|
||||
<input type="text" class="form-control" th:value="${factura.numeroFactura}"
|
||||
th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
<label class="form-label" th:text="#{facturas.form.numero-factura}">Número de factura</label>
|
||||
<input id="facturaNumero" type="text" class="form-control" th:value="${factura.numeroFactura}" readonly>
|
||||
</div>
|
||||
|
||||
<!-- Serie -->
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" th:text="#{facturas.form.serie}">Serie facturación</label>
|
||||
<select class="form-control js-select2-factura" data-url="/configuracion/series-facturacion/api/get-series" th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
<label class="form-label" th:text="#{facturas.form.serie}">Serie</label>
|
||||
<select id="facturaSerieId" class="form-control js-select2-factura"
|
||||
data-url="/configuracion/series-facturacion/api/get-series" th:attr="disabled=${isReadonly}">
|
||||
<option th:value="${factura.serie != null ? factura.serie.id : ''}"
|
||||
th:text="${factura.serie != null ? factura.serie.nombreSerie : ''}" selected>
|
||||
</option>
|
||||
@ -35,19 +35,20 @@
|
||||
<!-- Cliente -->
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" th:text="#{facturas.form.cliente}">Cliente</label>
|
||||
<select class="form-control js-select2-factura" data-url="/users/api/get-users" th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
<select id="facturaClienteId" class="form-control js-select2-factura" data-url="/users/api/get-users"
|
||||
th:attr="disabled=${isReadonly}">
|
||||
<option th:value="${factura.cliente != null ? factura.cliente.id : ''}"
|
||||
th:text="${factura.cliente != null ? factura.cliente.fullName : ''}" selected>
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Fecha emisión -->
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" th:text="#{facturas.form.fecha-emision}">Fecha</label>
|
||||
<input type="text" class="form-control" th:value="${factura.fechaEmision != null
|
||||
? #temporals.format(factura.fechaEmision, 'dd/MM/yyyy')
|
||||
: ''}" th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
|
||||
<input id="facturaFechaEmision" type="text" class="form-control"
|
||||
th:value="${factura.fechaEmision != null ? #temporals.format(factura.fechaEmision, 'dd/MM/yyyy') : ''}"
|
||||
th:attr="readonly=${isReadonly}, data-estado=${factura.estado.name()}">
|
||||
</div>
|
||||
|
||||
<!-- Notas -->
|
||||
@ -67,7 +68,7 @@
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" th:text="#{facturas.direccion.razon-social}">Razón Social</label>
|
||||
<input type="text" class="form-control" th:value="${direccionFacturacion != null
|
||||
<input type="text" id="dirRazonSocial" class="form-control" th:value="${direccionFacturacion != null
|
||||
? direccionFacturacion.razonSocial
|
||||
: ''}" th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
</div>
|
||||
@ -75,7 +76,7 @@
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" th:text="#{facturas.direccion.identificacion-fiscal}">Identificacion
|
||||
Fiscal</label>
|
||||
<input type="text" class="form-control" th:value="${direccionFacturacion != null
|
||||
<input type="text" id="dirIdentificacionFiscal" class="form-control" th:value="${direccionFacturacion != null
|
||||
? direccionFacturacion.identificacionFiscal
|
||||
: ''}" th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
</div>
|
||||
@ -83,39 +84,39 @@
|
||||
|
||||
<div class="col-md-9">
|
||||
<label class="form-label" th:text="#{facturas.direccion.direccion}">Dirección</label>
|
||||
<input type="text" class="form-control" th:value="${direccionFacturacion != null
|
||||
<input type="text" id="dirDireccion" class="form-control" th:value="${direccionFacturacion != null
|
||||
? direccionFacturacion.direccion
|
||||
: ''}" th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" th:text="#{facturas.direccion.codigo-postal}">Código Postal</label>
|
||||
<input type="text" class="form-control" th:value="${direccionFacturacion != null
|
||||
<input type="text" id="dirCp" class="form-control" th:value="${direccionFacturacion != null
|
||||
? direccionFacturacion.cp
|
||||
: ''}" th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" th:text="#{facturas.direccion.ciudad}">Ciudad</label>
|
||||
<input type="text" class="form-control" th:value="${direccionFacturacion != null
|
||||
<input type="text" id="dirCiudad" class="form-control" th:value="${direccionFacturacion != null
|
||||
? direccionFacturacion.ciudad
|
||||
: ''}" th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" th:text="#{facturas.direccion.provincia}">Provincia</label>
|
||||
<input type="text" class="form-control" th:value="${direccionFacturacion != null
|
||||
<input type="text" id="dirProvincia" class="form-control" th:value="${direccionFacturacion != null
|
||||
? direccionFacturacion.provincia
|
||||
: ''}" th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" th:text="#{facturas.direccion.pais}">País</label>
|
||||
<select class="form-control js-select2-factura" data-url="/api/paises" th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
<select id="dirPais" class="form-control js-select2-factura" data-url="/api/paises"
|
||||
th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
<option th:value="${direccionFacturacion != null
|
||||
? direccionFacturacion.pais.keyword
|
||||
: ''}"
|
||||
th:text="${direccionFacturacion != null
|
||||
? direccionFacturacion.pais.code3
|
||||
: ''}" th:text="${direccionFacturacion != null
|
||||
? #messages.msg('paises.' + direccionFacturacion.pais.keyword)
|
||||
: ''}" selected>
|
||||
</option>
|
||||
@ -124,7 +125,7 @@
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" th:text="#{facturas.direccion.telefono}">Teléfono</label>
|
||||
<input type="text" class="form-control" th:value="${direccionFacturacion != null
|
||||
<input type="text" id="dirTelefono" class="form-control" th:value="${direccionFacturacion != null
|
||||
? direccionFacturacion.telefono
|
||||
: ''}" th:attrappend="readonly=${isReadonly} ? 'readonly' : null">
|
||||
</div>
|
||||
@ -133,18 +134,18 @@
|
||||
<div class="row g-3 mt-4 justify-content-end">
|
||||
|
||||
<div class="col-md-12 text-end">
|
||||
<th:block th:if="${factura.estado.name() == 'borrador'}">
|
||||
<button type="button" class="btn btn-secondary me-2" id="btn-validar-factura"
|
||||
th:text="#{facturas.form.btn.validar}">Validar factura</button>
|
||||
<button type="button" class="btn btn-secondary me-2" id="btn-guardar-factura"
|
||||
th:text="#{facturas.form.btn.guardar}">Guardar</button>
|
||||
</th:block>
|
||||
<th:block th:if="${factura.estado.name() == 'validada'}">
|
||||
<button type="button" class="btn btn-secondary me-2" id="btn-borrador-factura"
|
||||
th:text="#{facturas.form.btn.borrador}">Pasar a borrador</button>
|
||||
</th:block>
|
||||
<button type="button" class="btn btn-secondary me-2" id="btn-imprimir-factura"
|
||||
th:text="#{facturas.form.btn.imprimir}">Imprimir factura</button>
|
||||
<th:block th:if="${factura.estado.name() == 'borrador'}">
|
||||
<button type="button" class="btn btn-secondary me-2" id="btn-validar-factura"
|
||||
th:text="#{facturas.form.btn.validar}">Validar factura</button>
|
||||
<button type="button" class="btn btn-secondary me-2" id="btn-guardar-factura"
|
||||
th:text="#{facturas.form.btn.guardar}">Guardar</button>
|
||||
</th:block>
|
||||
<th:block th:if="${factura.estado.name() == 'validada'}">
|
||||
<button type="button" class="btn btn-secondary me-2" id="btn-borrador-factura"
|
||||
th:text="#{facturas.form.btn.borrador}">Pasar a borrador</button>
|
||||
</th:block>
|
||||
<button type="button" class="btn btn-secondary me-2" id="btn-imprimir-factura"
|
||||
th:text="#{facturas.form.btn.imprimir}">Imprimir factura</button>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
<div id="pagos" class="accordion-collapse collapse show" aria-labelledby="pagosHeader"
|
||||
data-bs-parent="#pagosFactura">
|
||||
<div class="accordion-body">
|
||||
<!-- pagos -->
|
||||
<div th:replace="~{imprimelibros/facturas/partials/factura-pagos :: factura-pagos (factura=${factura})}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -7,10 +7,11 @@
|
||||
</button>
|
||||
</div>
|
||||
</th:block>
|
||||
<table class="table table-bordered table-striped table-nowrap w-100">
|
||||
<table class="table table-bordered table-striped table-wrap w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th th:if="${factura.estado != null && factura.estado.name() == 'borrador'}" th:text="#{facturas.lineas.acciones}">Acciones</th>
|
||||
<th th:if="${factura.estado != null && factura.estado.name() == 'borrador'}"
|
||||
th:text="#{facturas.lineas.acciones}">Acciones</th>
|
||||
<th class="w-75" th:text="#{facturas.lineas.descripcion}">Descripción</th>
|
||||
<th th:text="#{facturas.lineas.base}">Base</th>
|
||||
<th th:text="#{facturas.lineas.iva_4}">I.V.A. 4%</th>
|
||||
@ -21,16 +22,26 @@
|
||||
<tbody>
|
||||
<tr th:each="lineaFactura : ${factura.lineas}">
|
||||
<td th:if="${factura.estado != null && factura.estado.name() == 'borrador'}">
|
||||
<button type="button" class="btn btn-secondary btn-sm me-2"
|
||||
th:attr="data-linea-id=${lineaFactura.id}" th:text="#{facturas.lineas.acciones.editar}">
|
||||
<i class="fas fa-edit"></i>
|
||||
<button type="button" class="btn btn-secondary btn-sm me-2 btn-edit-linea-factura" th:attr="
|
||||
data-linea-id=${lineaFactura.id},
|
||||
data-base=${lineaFactura.baseLinea},
|
||||
data-iva4=${lineaFactura.iva4Linea},
|
||||
data-iva21=${lineaFactura.iva21Linea}
|
||||
">
|
||||
<i class="fas fa-edit me-1"></i>
|
||||
<span th:text="#{facturas.lineas.acciones.editar}">Editar</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-danger btn-sm"
|
||||
th:attr="data-linea-id=${lineaFactura.id}" th:text="#{facturas.lineas.acciones.eliminar}">
|
||||
|
||||
<button type="button" class="btn btn-danger btn-sm btn-delete-linea-factura" th:attr="data-linea-id=${lineaFactura.id}"
|
||||
th:text="#{facturas.lineas.acciones.eliminar}">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
|
||||
|
||||
<!-- IMPORTANTE: guardamos el HTML aquí (no en data-*) -->
|
||||
<textarea class="d-none" th:attr="id=${'linea-desc-' + lineaFactura.id}"
|
||||
th:text="${lineaFactura.descripcion}"></textarea>
|
||||
</td>
|
||||
|
||||
<td th:utext="${lineaFactura.descripcion}">Descripción de la línea</td>
|
||||
<td class="text-end" th:text="${#numbers.formatCurrency(lineaFactura.baseLinea)}">0.00</td>
|
||||
<td class="text-end" th:text="${#numbers.formatCurrency(lineaFactura.iva4Linea)}">0.00</td>
|
||||
@ -40,20 +51,33 @@
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td class="text-end fw-bold" th:attr="colspan=${factura.estado != null && factura.estado.name() == 'borrador' ? 5 : 4}" th:text="#{facturas.lineas.base}">Base</td>
|
||||
<td class="text-end fw-bold"
|
||||
th:attr="colspan=${factura.estado != null && factura.estado.name() == 'borrador' ? 5 : 4}"
|
||||
th:text="#{facturas.lineas.base}">Base</td>
|
||||
<td class="text-end" colspan="1" th:text="${#numbers.formatCurrency(factura.baseImponible)}">0.00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-end fw-bold" th:attr="colspan=${factura.estado != null && factura.estado.name() == 'borrador' ? 5 : 4}" th:text="#{facturas.lineas.iva_4}">I.V.A. 4%</td>
|
||||
<td class="text-end fw-bold"
|
||||
th:attr="colspan=${factura.estado != null && factura.estado.name() == 'borrador' ? 5 : 4}"
|
||||
th:text="#{facturas.lineas.iva_4}">I.V.A. 4%</td>
|
||||
<td class="text-end" colspan="1" th:text="${#numbers.formatCurrency(factura.iva4)}">0.00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-end fw-bold" th:attr="colspan=${factura.estado != null && factura.estado.name() == 'borrador' ? 5 : 4}" th:text="#{facturas.lineas.iva_21}">I.V.A. 21%</td>
|
||||
<td class="text-end fw-bold"
|
||||
th:attr="colspan=${factura.estado != null && factura.estado.name() == 'borrador' ? 5 : 4}"
|
||||
th:text="#{facturas.lineas.iva_21}">I.V.A. 21%</td>
|
||||
<td class="text-end" colspan="1" th:text="${#numbers.formatCurrency(factura.iva21)}">0.00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-end fw-bold text-uppercase" th:attr="colspan=${factura.estado != null && factura.estado.name() == 'borrador' ? 5 : 4}" th:text="#{facturas.lineas.total}">Total</td>
|
||||
<td class="text-end fw-bold" colspan="1" th:text="${#numbers.formatCurrency(factura.totalFactura)}">0.00</td>
|
||||
<td class="text-end fw-bold text-uppercase"
|
||||
th:attr="colspan=${factura.estado != null && factura.estado.name() == 'borrador' ? 5 : 4}"
|
||||
th:text="#{facturas.lineas.total}">Total</td>
|
||||
<td class="text-end fw-bold" colspan="1" th:text="${#numbers.formatCurrency(factura.totalFactura)}">0.00
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- Modal líneas factura (crear/editar) -->
|
||||
<th:block th:replace="~{imprimelibros/facturas/partials/linea-modal :: linea-modal}"></th:block>
|
||||
|
||||
</div>
|
||||
@ -0,0 +1,69 @@
|
||||
<!-- imprimelibros/facturas/partials/factura-pagos.html -->
|
||||
<div th:fragment="factura-pagos (factura)">
|
||||
<div class="mb-3">
|
||||
<button type="button" class="btn btn-secondary" id="btn-add-pago-factura">
|
||||
<i class="fas fa-plus-circle me-2"></i>
|
||||
<span th:text="#{facturas.pagos.acciones.agregar}">Agregar pago</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered table-striped table-wrap w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th th:text="#{facturas.pagos.acciones}">Acciones</th>
|
||||
<th th:text="#{facturas.pagos.metodo}">Método</th>
|
||||
<th th:text="#{facturas.pagos.fecha}">Fecha</th>
|
||||
<th class="text-center w-50" th:text="#{facturas.pagos.notas}">Notas</th>
|
||||
<th class="text-end" th:text="#{facturas.pagos.cantidad}">Cantidad</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="pago : ${factura.pagos}" th:if="${pago.deletedAt == null}">
|
||||
<td>
|
||||
<button type="button" class="btn btn-secondary btn-sm me-2 btn-edit-pago-factura" th:attr="
|
||||
data-pago-id=${pago.id},
|
||||
data-metodo=${pago.metodoPago},
|
||||
data-cantidad=${pago.cantidadPagada},
|
||||
data-fecha=${#temporals.format(pago.fechaPago,'yyyy-MM-dd')}">
|
||||
<i class="fas fa-edit me-1"></i>
|
||||
<span th:text="#{facturas.pagos.acciones.editar}">Editar</span>
|
||||
</button>
|
||||
|
||||
<button type="button" class="btn btn-danger btn-sm btn-delete-pago-factura"
|
||||
th:attr="data-pago-id=${pago.id}">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
<span th:text="#{facturas.pagos.acciones.eliminar}">Eliminar</span>
|
||||
</button>
|
||||
|
||||
<!-- notas en HTML (igual que líneas: guardadas en textarea oculto) -->
|
||||
<textarea class="d-none" th:attr="id=${'pago-notas-' + pago.id}" th:text="${pago.notas}"></textarea>
|
||||
</td>
|
||||
|
||||
<td th:text="${#messages.msg('facturas.pagos.tipo.' + pago.metodoPago.name().toLowerCase())}">
|
||||
TPV/Tarjeta
|
||||
</td>
|
||||
|
||||
<!-- Formato visual dd/MM/yyyy -->
|
||||
<td th:text="${#temporals.format(pago.fechaPago,'dd/MM/yyyy')}">01/01/2026 10:00</td>
|
||||
|
||||
<td class="text-muted">
|
||||
<span th:if="${pago.notas == null || #strings.isEmpty(pago.notas)}">—</span>
|
||||
<span th:if="${pago.notas != null && !#strings.isEmpty(pago.notas)}"
|
||||
th:utext="${pago.notas}"></span>
|
||||
</td>
|
||||
|
||||
<td class="text-end" th:text="${#numbers.formatCurrency(pago.cantidadPagada)}">0,00 €</td>
|
||||
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th colspan="4" class="text-end" th:text="#{facturas.pagos.total_pagado}">Total pagado</th>
|
||||
<th class="text-end" th:text="${#numbers.formatCurrency(factura.totalPagado)}">0,00 €</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<!-- Modal pagos (crear/editar) -->
|
||||
<th:block th:replace="~{imprimelibros/facturas/partials/pago-modal :: pago-modal}"></th:block>
|
||||
</div>
|
||||
@ -0,0 +1,79 @@
|
||||
<!-- imprimelibros/facturas/partials/linea-modal.html -->
|
||||
<div th:fragment="linea-modal">
|
||||
<div class="modal fade" id="lineaFacturaModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="lineaFacturaModalTitle" th:text="#{facturas.lineas.titulo}">Línea de factura</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<!-- hidden: id de la línea (vacío = nueva) -->
|
||||
<input type="hidden" id="lineaFacturaId" value=""/>
|
||||
|
||||
<!-- Descripción con Quill -->
|
||||
<div class="mb-3">
|
||||
<label class="form-label" th:text="#{facturas.lineas.descripcion}">Descripción</label>
|
||||
|
||||
<!-- Quill Snow Editor -->
|
||||
<div id="lineaFacturaDescripcionEditor"
|
||||
class="snow-editor" style="min-height: 200px;"
|
||||
data-contenido=""></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="lineaFacturaBase" class="form-label"
|
||||
th:text="#{facturas.lineas.base}">Base</label>
|
||||
<input type="text"
|
||||
class="form-control text-end"
|
||||
id="lineaFacturaBase"
|
||||
inputmode="decimal"
|
||||
autocomplete="off"
|
||||
placeholder="0,00">
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="lineaFacturaIva4" class="form-label"
|
||||
th:text="#{facturas.lineas.iva_4}">I.V.A. 4%</label>
|
||||
<input type="text"
|
||||
class="form-control text-end"
|
||||
id="lineaFacturaIva4"
|
||||
inputmode="decimal"
|
||||
autocomplete="off"
|
||||
placeholder="0,00">
|
||||
<div class="form-text" th:text="#{facturas.lineas.iva_4.help}">Introduce el importe del I.V.A. (no el %).</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="lineaFacturaIva21" class="form-label"
|
||||
th:text="#{facturas.lineas.iva_21}">I.V.A. 21%</label>
|
||||
<input type="text"
|
||||
class="form-control text-end"
|
||||
id="lineaFacturaIva21"
|
||||
inputmode="decimal"
|
||||
autocomplete="off"
|
||||
placeholder="0,00">
|
||||
<div class="form-text" th:text="#{facturas.lineas.iva_21.help}">Introduce el importe del I.V.A. (no el %).</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- zona errores -->
|
||||
<div class="alert alert-danger d-none mt-3" id="lineaFacturaModalError"></div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal" th:text="#{app.cancelar}">Cancelar</button>
|
||||
<button type="button" class="btn btn-secondary" id="btnGuardarLineaFactura" th:text="#{app.guardar}">
|
||||
Guardar
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,66 @@
|
||||
<!-- imprimelibros/facturas/partials/pago-modal.html -->
|
||||
<div th:fragment="pago-modal">
|
||||
<div class="modal fade" id="pagoFacturaModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="pagoFacturaModalTitle" th:text="#{facturas.pagos.titulo}">
|
||||
Pago de factura
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="pagoFacturaId" value="" />
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="pagoFacturaMetodo" class="form-label"
|
||||
th:text="#{facturas.pagos.tipo}">Tipo de pago</label>
|
||||
<select class="form-select" id="pagoFacturaMetodo">
|
||||
<option value="tpv_tarjeta" th:text="#{facturas.pagos.tipo.tpv_tarjeta}">TPV/Tarjeta
|
||||
</option>
|
||||
<option value="tpv_bizum" th:text="#{facturas.pagos.tipo.tpv_bizum}">TPV/Bizum</option>
|
||||
<option value="transferencia" th:text="#{facturas.pagos.tipo.transferencia}">
|
||||
Transferencia</option>
|
||||
<option value="otros" th:text="#{facturas.pagos.tipo.otros}">Otros</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="pagoFacturaCantidad" class="form-label"
|
||||
th:text="#{facturas.pagos.cantidad}">Cantidad</label>
|
||||
<input type="text" class="form-control text-end" id="pagoFacturaCantidad"
|
||||
inputmode="decimal" autocomplete="off" placeholder="0,00">
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="pagoFacturaFecha" class="form-label" th:text="#{facturas.pagos.fecha}">Fecha de
|
||||
pago</label>
|
||||
<input type="text" class="form-control" id="pagoFacturaFecha" autocomplete="off"
|
||||
placeholder="dd/mm/aaaa hh:mm">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<label class="form-label" th:text="#{facturas.pagos.notas}">Notas</label>
|
||||
<div id="pagoFacturaNotasEditor" class="snow-editor" style="min-height: 180px;"
|
||||
data-contenido=""></div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger d-none mt-3" id="pagoFacturaModalError"></div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal"
|
||||
th:text="#{app.cancelar}">Cancelar</button>
|
||||
<button type="button" class="btn btn-secondary" id="btnGuardarPagoFactura" th:text="#{app.guardar}">
|
||||
Guardar
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -14,6 +14,7 @@
|
||||
<th:block th:replace="~{imprimelibros/partials/head-css :: head-css}" />
|
||||
<link href="/assets/libs/sweetalert2/sweetalert2.min.css" rel="stylesheet" type="text/css" />
|
||||
<link href="/assets/libs/select2/select2.min.css" rel="stylesheet" />
|
||||
<link rel="stylesheet" th:href="@{/assets/libs/flatpickr/flatpickr.min.css}">
|
||||
<th:block layout:fragment="pagecss" />
|
||||
</head>
|
||||
|
||||
@ -38,6 +39,13 @@
|
||||
<script src="/assets/libs/jquery/jquery-3.6.0.min.js"></script>
|
||||
<script src="/assets/libs/sweetalert2/sweetalert2.min.js"></script>
|
||||
<script src="/assets/libs/select2/select2.min.js"></script>
|
||||
<script defer th:src="@{/assets/libs/flatpickr/flatpickr.min.js}"></script>
|
||||
<th:block th:with="fpLang=${#locale.language}">
|
||||
<script defer th:src="@{'/assets/libs/flatpickr/l10n/' + ${fpLang} + '.js'}"
|
||||
onerror="console.error('No se pudo cargar flatpickr locale:', this.src)">
|
||||
</script>
|
||||
</th:block>
|
||||
|
||||
<th:block layout:fragment="pagejs" />
|
||||
<script th:src="@{/assets/js/app.js}"></script>
|
||||
<script th:src="@{/assets/js/pages/imprimelibros/languageBundle.js}"></script>
|
||||
|
||||
165
src/main/resources/templates/imprimelibros/pdf/factura-a4.html
Normal file
165
src/main/resources/templates/imprimelibros/pdf/factura-a4.html
Normal file
@ -0,0 +1,165 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="es">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title th:text="'Factura ' + ${factura.numeroFactura}">Factura</title>
|
||||
<link rel="stylesheet" href="assets/css/bootstrap-for-pdf.css" />
|
||||
<link rel="stylesheet" href="assets/css/facturapdf.css" />
|
||||
</head>
|
||||
|
||||
<body class="has-watermark">
|
||||
|
||||
<div class="watermark">
|
||||
<img src="assets/images/logo-watermark.png" alt="Marca de agua" />
|
||||
</div>
|
||||
|
||||
<!-- PIE -->
|
||||
<div class="pdf-footer-source">
|
||||
<div class="footer" id="pdf-footer">
|
||||
|
||||
<div class="privacy">
|
||||
<div class="pv-title" th:text="#{pdf.politica-privacidad}">Política de privacidad</div>
|
||||
<div class="pv-text" th:text="#{pdf.politica-privacidad.responsable}">Responsable: Impresión Imprime Libros -
|
||||
CIF:
|
||||
B04998886 - Teléfono de contacto: 910052574</div>
|
||||
<div class="pv-text" th:text="#{pdf.politica-privacidad.correo-direccion}">Correo electrónico:
|
||||
info@imprimelibros.com - Dirección postal: Calle José Picón, Nº 28 Local A, 28028, Madrid</div>
|
||||
<div class="pv-text" th:text="#{pdf.politica-privacidad.aviso}">
|
||||
Le comunicamos que los datos que usted nos facilite quedarán incorporados
|
||||
en nuestro registro interno de actividades de tratamiento con el fin de
|
||||
llevar a cabo una adecuada gestión fiscal y contable.
|
||||
Los datos proporcionados se conservarán mientras se mantenga la relación
|
||||
comercial o durante los años necesarios para cumplir con las obligaciones legales.
|
||||
Así mismo, los datos no serán cedidos a terceros salvo en aquellos casos en que exista
|
||||
una obligación legal. Tiene derecho a acceder a sus datos personales, rectificar
|
||||
los datos inexactos, solicitar su supresión, limitar alguno de los tratamientos
|
||||
u oponerse a algún uso vía e-mail, personalmente o mediante correo postal.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-number">
|
||||
<span th:text="#{pdf.page} ?: 'Página'">Página</span>
|
||||
<span class="pn"></span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<!-- HEADER: logo izq + caja empresa dcha -->
|
||||
|
||||
<!-- HEADER: logo izq + caja empresa dcha (tabla, sin flex) -->
|
||||
<table class="il-header">
|
||||
<tr>
|
||||
<td class="il-left">
|
||||
<img src="assets/images/logo-light.png" alt="ImprimeLibros" class="il-logo" />
|
||||
</td>
|
||||
<td class="il-right">
|
||||
<div class="il-company-box">
|
||||
<span class="corner tl"></span>
|
||||
<span class="corner tr"></span>
|
||||
<span class="corner bl"></span>
|
||||
<span class="corner br"></span>
|
||||
|
||||
<div class="company-line company-name" th:text="#{pdf.company.name} ?: 'ImprimeLibros'">
|
||||
ImprimeLibros ERP</div>
|
||||
<div class="company-line" th:text="#{pdf.company.address} ?: ''">C/ José Picón, 28 local A</div>
|
||||
<div class="company-line">
|
||||
<span th:text="#{pdf.company.postalcode} ?: '28028'">28028</span>
|
||||
<span th:text="#{pdf.company.city} ?: 'Madrid'">Madrid</span>
|
||||
</div>
|
||||
<div class="company-line" th:text="#{pdf.company.phone} ?: '+34 910052574'">+34 910052574</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<!-- BANDA SUPERIOR -->
|
||||
<div class="doc-banner">
|
||||
<div th:text="#{pdf.factura} ?: 'FACTURA'" class="banner-text">FACTURA</div>
|
||||
</div>
|
||||
|
||||
<!-- FICHA Nº / CLIENTE / FECHA -->
|
||||
<table class="sheet-info">
|
||||
<tr>
|
||||
<td class="text-start w-50"><span th:text="#{'pdf.factura.number'}" class="lbl">FACTURA Nº:</span> <span
|
||||
class="val" th:text="${factura.numeroFactura}">153153</span></td>
|
||||
<td class="text-end"><span class="lbl" th:text="#{pdf.presupuesto.date}">FECHA:</span> <span class="val"
|
||||
th:text="${#temporals.format(factura.fechaEmision, 'dd/MM/yyyy')}">10/10/2025</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="sheet-info">
|
||||
<tr>
|
||||
<td class="text-start"><span th:text="#{'pdf.factura.razon-social'}" class="lbl">Razón Social:</span> <span
|
||||
class="val" th:text="${direccionFacturacion.razonSocial}">153153</span></td>
|
||||
<td class="text-end"><span th:text="#{'pdf.factura.direccion'}" class="lbl">Dirección:</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-start"><span th:text="#{'pdf.factura.identificacion-fiscal'}" class="lbl">Identificación
|
||||
Fiscal:</span> <span class="val" th:text="${direccionFacturacion.identificacionFiscal}">153153</span></td>
|
||||
<td class="text-end">
|
||||
<span class="val"
|
||||
th:text="${direccionFacturacion.direccion + ', ' + direccionFacturacion.cp + ', ' + direccionFacturacion.ciudad}">153153</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-start">
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<span class="val"
|
||||
th:text="${direccionFacturacion.provincia + ', ' + #messages.msg('paises.' + direccionFacturacion.pais.keyword)}">153153</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- DATOS TÉCNICOS -->
|
||||
<table class="items-table table table-bordered table-striped table-wrap w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-75" th:text="#{pdf.factura.lineas.descripcion}">Descripción</th>
|
||||
<th th:text="#{pdf.factura.lineas.base}">Base</th>
|
||||
<th th:text="#{pdf.factura.lineas.iva_4}">I.V.A. 4%</th>
|
||||
<th th:text="#{pdf.factura.lineas.iva_21}">I.V.A. 21%</th>
|
||||
<th th:text="#{pdf.factura.lineas.total}">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="lineaFactura : ${factura.lineas}">
|
||||
<td th:utext="${lineaFactura.descripcion}">Descripción de la línea</td>
|
||||
<td class="text-end" th:text="${#numbers.formatCurrency(lineaFactura.baseLinea)}">0.00</td>
|
||||
<td class="text-end" th:text="${#numbers.formatCurrency(lineaFactura.iva4Linea)}">0.00</td>
|
||||
<td class="text-end" th:text="${#numbers.formatCurrency(lineaFactura.iva21Linea)}">0.00</td>
|
||||
<td class="text-end" th:text="${#numbers.formatCurrency(lineaFactura.totalLinea)}">0.00</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td class="text-end fw-bold" colspan="4" th:text="#{pdf.factura.lineas.base}">Base</td>
|
||||
<td class="text-end" colspan="1" th:text="${#numbers.formatCurrency(factura.baseImponible)}">0.00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-end fw-bold" colspan="4" th:text="#{pdf.factura.lineas.iva_4}">I.V.A. 4%</td>
|
||||
<td class="text-end" colspan="1" th:text="${#numbers.formatCurrency(factura.iva4)}">0.00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-end fw-bold" colspan="4" th:text="#{pdf.factura.lineas.iva_21}">I.V.A. 21%</td>
|
||||
<td class="text-end" colspan="1" th:text="${#numbers.formatCurrency(factura.iva21)}">0.00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-end fw-bold text-uppercase" colspan="4" th:text="#{pdf.factura.lineas.total}">Total</td>
|
||||
<td class="text-end fw-bold" colspan="1" th:text="${#numbers.formatCurrency(factura.totalFactura)}">0.00
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user