diff --git a/src/main/java/com/imprimelibros/erp/pdf/TemplateRegistry.java b/src/main/java/com/imprimelibros/erp/pdf/TemplateRegistry.java index 71f19c1..12008f7 100644 --- a/src/main/java/com/imprimelibros/erp/pdf/TemplateRegistry.java +++ b/src/main/java/com/imprimelibros/erp/pdf/TemplateRegistry.java @@ -8,7 +8,6 @@ public class TemplateRegistry { public TemplateRegistry(PdfModuleConfig config) { this.config = config; - System.out.println("PDF templates registrados => " + config.getTemplates()); } public String resolve(DocumentType type, String templateId) { diff --git a/src/main/resources/i18n/pdf_en.properties b/src/main/resources/i18n/pdf_en.properties new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/i18n/pdf_es.properties b/src/main/resources/i18n/pdf_es.properties new file mode 100644 index 0000000..4b71644 --- /dev/null +++ b/src/main/resources/i18n/pdf_es.properties @@ -0,0 +1,21 @@ +pdf.company.name=Impresión ImprimeLibros S.L. +pdf.company.address=C/ José Picón, 28 local A +pdf.company.postalcode=28028 +pdf.company.city=Madrid +pdf.company.phone=+34 910052574 + +pdf.presupuesto=PRESUPUESTO +pdf.factura=FACTURA +pdf.pedido=PEDIDO + +# Presupuesto +pdf.presupuesto.number=PRESUPUESTO Nº: +pdf.presupuesto.client=CLIENTE: +pdf.presupuesto.date=FECHA: + +pdf.presupuesto.titulo=Título: + +pdf.politica-privacidad=Política de privacidad +pdf.politica-privacidad.responsable=Responsable: Impresión Imprime Libros - CIF: B04998886 - Teléfono de contacto: 910052574 +pdf.politica-privacidad.correo-direccion=Correo electrónico: info@imprimelibros.com - Dirección postal: Calle José Picón, Nº 28 Local A, 28028, Madrid +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. \ No newline at end of file diff --git a/src/main/resources/i18n/presupuesto_es.properties b/src/main/resources/i18n/presupuesto_es.properties index f6d2736..f05835b 100644 --- a/src/main/resources/i18n/presupuesto_es.properties +++ b/src/main/resources/i18n/presupuesto_es.properties @@ -72,6 +72,15 @@ presupuesto.espiral-descripcion=Espiral (a partir de 20 páginas) presupuesto.wire-o=Wire-O presupuesto.wireo=Wire-O presupuesto.wire-o-descripcion=Wire-O (a partir de 20 páginas) +presupuesto.informacion-adicional=Información adicional +presupuesto.informacion-adicional-descripcion=Datos adicionales +presupuesto.iva-reducido=I.V.A reducido +presupuesto.iva-reducido-descripcion=Se verificará que el pedido cumpla con los requisitos establecidos en el Artículo 91 de la Ley 37/1992, sobre inserción de publicidad, antes de proceder con su producción, lo que garantiza la aplicación del IVA reducido del 4%. +presupuesto.entrega=Entrega +presupuesto.entrega.peninsula=Península y Baleares +presupuesto.entrega.canarias=Canarias +presupuesto.entrega.paises-ue=Países UE + presupuesto.encuadernacion-descripcion=Seleccione la encuadernación del libro presupuesto.continuar-interior=Continuar a diseño interior diff --git a/src/main/resources/static/assets/css/bootstrap-for-pdf.css b/src/main/resources/static/assets/css/bootstrap-for-pdf.css new file mode 100644 index 0000000..598f91e --- /dev/null +++ b/src/main/resources/static/assets/css/bootstrap-for-pdf.css @@ -0,0 +1,59 @@ +/* ======================= + Bootstrap for PDF (compatible con OpenHTMLtoPDF) + ======================= */ + +/* -- TEXT ALIGN -- */ +.text-start { text-align: left !important; } +.text-center { text-align: center !important; } +.text-end { text-align: right !important; } + +/* -- FONT WEIGHT -- */ +.fw-normal { font-weight: 400 !important; } +.fw-semibold { font-weight: 600 !important; } +.fw-bold { font-weight: 700 !important; } + +/* -- SPACING (margin/padding) -- */ +.mt-1 { margin-top: 0.25rem !important; } +.mt-2 { margin-top: 0.5rem !important; } +.mt-3 { margin-top: 1rem !important; } +.mb-1 { margin-bottom: 0.25rem !important; } +.mb-2 { margin-bottom: 0.5rem !important; } +.mb-3 { margin-bottom: 1rem !important; } + +.p-1 { padding: 0.25rem !important; } +.p-2 { padding: 0.5rem !important; } +.p-3 { padding: 1rem !important; } + +/* -- TABLE -- */ +.table { + width: 100%; + border-collapse: collapse; + font-size: 10.5pt; +} + +.table th, +.table td { + padding: 6px; + border: 1px solid #dee2e6; +} + +.table thead th { + background-color: #f8f9fa; + font-weight: 700; +} + +/* -- BORDER -- */ +.border { + border: 1px solid #dee2e6 !important; +} + +.border-0 { border: 0 !important; } + +/* -- BACKGROUND -- */ +.bg-light { background-color: #f8f9fa !important; } +.bg-white { background-color: #fff !important; } + +/* -- DISPLAY UTILS (limited) -- */ +.d-block { display: block !important; } +.d-inline { display: inline !important; } +.d-inline-block { display: inline-block !important; } diff --git a/src/main/resources/static/assets/css/presupuestador.css b/src/main/resources/static/assets/css/presupuestador.css index 6d6a116..060f000 100644 --- a/src/main/resources/static/assets/css/presupuestador.css +++ b/src/main/resources/static/assets/css/presupuestador.css @@ -414,6 +414,7 @@ .form-switch-presupuesto .form-check-input:checked { border-color: #92b2a7; + background-color: #cbcecd; } .form-switch-custom.form-switch-presupuesto .form-check-input:checked::before { diff --git a/src/main/resources/static/assets/css/presupuestopdf.css b/src/main/resources/static/assets/css/presupuestopdf.css index 1b1063a..165d183 100644 --- a/src/main/resources/static/assets/css/presupuestopdf.css +++ b/src/main/resources/static/assets/css/presupuestopdf.css @@ -1,54 +1,169 @@ +:root { + --verde: #92b2a7; + --letterspace: 8px; + /* ← puedes ajustar este valor en el root */ + -ink: #1b1e28; + --muted: #5b6472; + --accent: #0ea5e9; + /* azul tira a cyan */ + --line: #e6e8ef; + --bg-tag: #f4f7fb; +} + /* Open Sans (rutas relativas desde css → fonts) */ @font-face { font-family: "Open Sans"; src: url("../fonts/OpenSans-Regular.ttf") format("truetype"); font-weight: 400; } + @font-face { font-family: "Open Sans"; src: url("../fonts/OpenSans-SemiBold.ttf") format("truetype"); font-weight: 600; } + @font-face { font-family: "Open Sans"; src: url("../fonts/OpenSans-Bold.ttf") format("truetype"); font-weight: 700; } -:root { - --ink: #1b1e28; - --muted: #5b6472; - --accent: #0ea5e9; /* azul tira a cyan */ - --line: #e6e8ef; - --bg-tag: #f4f7fb; -} @page { size: A4; - margin: 15mm 14mm 18mm 14mm; - @bottom-right { content: "Página " counter(page) " / " counter(pages); } + margin: 0; } -html, body { - font-family: "Open Sans", Arial, sans-serif; +html, +body { + font-family: "Open Sans" !important; color: var(--ink); font-size: 11pt; line-height: 1.35; } -/* Top band */ -.topbar { - display: table; - width: 100%; - border-bottom: 2px solid var(--accent); - padding-bottom: 6mm; - margin-bottom: 6mm; +.page-content { + padding: 15mm 14mm 28mm 14mm; /* ↑ deja 10mm extra para no pisar el footer */ + box-sizing: border-box; /* para que el padding no desborde */ } -.brand { display: table-cell; width: 60%; vertical-align: top; } -.logo { height: 30px; display: block; margin-bottom: 4px; } -.brand-name { font-weight: 700; } -.brand-meta { color: var(--muted); font-size: 9.5pt; } -.doc-title { display: table-cell; width: 40%; text-align: right; font-weight: 700; letter-spacing: 3px; } + + +body.has-watermark { + background-image: none !important; +} + +/* ====== HEADER (tabla) ====== */ +.il-header { + width: 100%; + border-collapse: collapse; + margin: 0 0 8mm 0; + /* ↓ espacio bajo el header */ +} + +.il-left, +.il-right { + vertical-align: middle; +} + +.il-left { + width: 50%; +} + +.il-right { + width: 50%; + text-align: right; +} + +.il-logo { + height: 70px; +} + +/* ← tamaño logo */ + +/* Caja superior derecha con esquinas */ +.il-company-box { + display: inline-block; + align-items: end; + /* para alinear a la derecha sin ocupar todo */ + position: relative; + padding: 4mm 4mm; + /* ← espacio texto ↔ esquinas */ + color: #000; + font-size: 10.5pt; + /* ← tamaño de letra */ + line-height: 1; + /* ← separación entre líneas */ + max-width: 75mm; + /* ← ancho máximo de la caja */ + text-align: center; +} + +/* Esquinas */ +.il-company-box .corner { + position: absolute; + width: 20px; + /* ← anchura esquina */ + height: 20px; + /* ← altura esquina */ + border-color: #92b2a7; + /* ← color esquina */ +} + +.corner.tl { + top: 0; + left: 0; + border-top: 2px solid #92b2a7; + border-left: 2px solid #92b2a7; +} + +.corner.tr { + top: 0; + right: 0; + border-top: 2px solid #92b2a7; + border-right: 2px solid #92b2a7; +} + +.corner.bl { + bottom: 0; + left: 0; + border-bottom: 2px solid #92b2a7; + border-left: 2px solid #92b2a7; +} + +.corner.br { + bottom: 0; + right: 0; + border-bottom: 2px solid #92b2a7; + border-right: 2px solid #92b2a7; +} + + +.company-line { + margin: 1.5mm 0; +} + + + +/* Nueva banda verde PRESUPUESTO */ +.doc-banner { + width: 100%; + background-color: #92b2a7 !important; /* ← tu verde corporativo */ + color: white; + text-align: center; + padding: 2mm 0; + margin-bottom: 4mm; + display: block; /* evita conflictos */ +} + +.banner-text { + font-family: "Open Sans", Arial, sans-serif !important; + font-weight: 400; + font-size: 20pt; + letter-spacing: 8px; /* ← configurable */ +} + + /* ficha superior */ .sheet-info { @@ -57,41 +172,99 @@ html, body { margin: 4mm 0 6mm 0; font-size: 10.5pt; } + .sheet-info td { border: 1px solid var(--line); padding: 4px 6px; } -.sheet-info .lbl { color: var(--muted); margin-right: 4px; } -.sheet-info .val { font-weight: 700; } + +.sheet-info .lbl { + color: var(--muted); + margin-right: 4px; +} + +/*.sheet-info .val { +}*/ /* Línea título libro */ .line-title { + font-family: "Open Sans", Arial, sans-serif !important; margin: 3mm 0 5mm 0; - padding: 4px 6px; - background: var(--bg-tag); - border-left: 3px solid var(--accent); + padding: 2px 4px; font-size: 10.5pt; + font-weight: 600; + color: #5c5c5c; +} + +.line-title .lbl { + margin-right: 6px; + font-weight: 600; } -.line-title .lbl { color: var(--muted); margin-right: 6px; font-weight: 600; } /* Specs 2 columnas */ -.specs { display: table; width: 100%; table-layout: fixed; margin-bottom: 6mm; } -.specs .col { display: table-cell; width: 50%; padding-right: 6mm; vertical-align: top; } -.specs .col:last-child { padding-right: 0; } +.specs-wrapper { + width: 180mm; + margin-left: 15mm; /* ← margen izquierdo real del A4 */ + margin-right: auto; /* opcional */ + color: #5c5c5c; +} + +.align-with-text { + margin-left: 1mm; + margin-right: 0; + width: auto; +} + +.specs { + display: table; + width: 100%; + table-layout: fixed; + margin-bottom: 6mm; +} +.specs .col { + display: table-cell; + width: 50%; + padding-right: 6mm; + vertical-align: top; +} +.specs .col:last-child { + padding-right: 0; +} + .block-title { text-transform: uppercase; font-weight: 700; color: var(--accent); - font-size: 10pt; + font-size: 8pt; margin: 2mm 0 1mm 0; } -.kv { margin: 1mm 0; } -.kv span { color: var(--muted); display: inline-block; min-width: 55%; } -.kv b { font-weight: 600; } -.subblock { margin-top: 3mm; } -.services { margin: 0; padding-left: 14px; } -.services li { margin: 1mm 0; } +.kv { + margin: 1mm 0; +} + +.kv span { + color: var(--muted); + display: inline-block; + min-width: 55%; +} + +.kv b { + font-weight: 600; +} + +.subblock { + margin-top: 3mm; +} + +.services { + margin: 0; + padding-left: 14px; +} + +.services li { + margin: 1mm 0; +} /* Bloque marcapáginas */ .bookmark { @@ -100,8 +273,10 @@ html, body { padding: 3mm; background: #fff; } + .bookmark .bk-title { - font-weight: 700; margin-bottom: 2mm; + font-weight: 700; + margin-bottom: 2mm; } /* Tabla de precios (tiradas) */ @@ -111,6 +286,7 @@ html, body { margin-top: 6mm; font-size: 10.5pt; } + .prices thead th { text-align: left; padding: 6px; @@ -118,27 +294,81 @@ html, body { background: #eef8fe; font-weight: 700; } + .prices tbody td { border-bottom: 1px solid var(--line); padding: 6px; } -.prices .col-tirada { width: 22%; font-weight: 700; } + +.prices .col-tirada { + width: 22%; + font-weight: 700; +} /* Footer */ + .footer { - margin-top: 8mm; + position: fixed; + left: 14mm; + right: 14mm; + bottom: 18mm; border-top: 1px solid var(--line); padding-top: 4mm; - display: table; - width: 100%; - font-size: 9.5pt; + font-size: 7.5pt; + color: var(--muted); + z-index: 10; /* sobre la marca */ + background: transparent; +} + + +.footer .address { + display: table-cell; + width: 45%; +} + +.footer .privacy { + display: table-cell; + width: 55%; +} + +.pv-title { + font-weight: 700; + margin-bottom: 1mm; + color: var(--ink); +} + +.pv-text { + line-height: 1.25; +} + +.page-count { + margin-top: 2mm; + text-align: right; + font-size: 9pt; color: var(--muted); } -.footer .address { display: table-cell; width: 45%; } -.footer .privacy { display: table-cell; width: 55%; } -.pv-title { font-weight: 700; margin-bottom: 1mm; color: var(--ink); } -.pv-text { line-height: 1.25; } -.page-count { margin-top: 2mm; text-align: right; font-size: 9pt; color: var(--muted); } -.page::after { content: counter(page); } -.pages::after { content: counter(pages); } +.page::after { + content: counter(page); +} + +.pages::after { + content: counter(pages); +} + +/* Caja a página completa SIN vw/vh y SIN z-index negativo */ +.watermark { + position: fixed; + top: 0; left: 0; right: 0; bottom: 0; /* ocupa toda la HOJA */ + pointer-events: none; + z-index: 0; /* debajo del contenido */ +} + +.watermark img { + position: absolute; + top: 245mm; /* baja/sube (70–85%) */ + left: 155mm; /* desplaza a la derecha si quieres */ + transform: translate(-50%, -50%) rotate(-15deg); + width: 60%; /* tamaño grande, ya no hay recorte por márgenes */ + max-width: none; +} diff --git a/src/main/resources/static/assets/images/logo-watermark.png b/src/main/resources/static/assets/images/logo-watermark.png new file mode 100644 index 0000000..87a3522 Binary files /dev/null and b/src/main/resources/static/assets/images/logo-watermark.png differ diff --git a/src/main/resources/templates/imprimelibros/pdf/presupuesto-a4.html b/src/main/resources/templates/imprimelibros/pdf/presupuesto-a4.html index 6e58aeb..06f4e45 100644 --- a/src/main/resources/templates/imprimelibros/pdf/presupuesto-a4.html +++ b/src/main/resources/templates/imprimelibros/pdf/presupuesto-a4.html @@ -1,142 +1,199 @@ + Presupuesto + - - -
-
- -
-
ImprimeLibros ERP
-
- C. José Picón, 28 local A · 28028 Madrid - · 910052574 - · info@imprimelibros.com - · B04998886 -
-
-
-
P R E S U P U E S T O
+ + + +
+ Marca de agua
- - - - - - - -
PRESUPUESTO Nº: 153153CLIENTE: JUAN JOSÉ MÉNDEZFECHA: 10/10/2025
+
+ - -
- Título: - Libro de prueba -
- - -
-
-
Encuadernación
-
Encuadernación:Fresado
-
Formato: - 148x210 mm -
-
Páginas:132
-
Páginas Negro:100
-
Páginas Color:32
- -
-
Interior
-
Tipo de impresión:Color Premium
-
Papel interior:Estucado Mate
-
Gramaje interior:115
-
-
- -
-
-
Cubierta
-
Tipo de cubierta:Tapa blanda
-
Solapas:
-
Tamaño solapas:80 mm
-
Impresión:Una cara
-
Papel cubierta:Estucado mate
-
Gramaje cubierta:250
-
Acabado:Plastificado Brillo 1/C
-
- -
-
Servicios Extras
- -
-
    -
  • - Ferro Digital - 0,00 € -
  • -
-
- - -
-
Marcapáginas
-
Tamaño:50x210
-
Papel:Estucado mate 300 g
-
Impresión:Una cara
-
Plastificado:Brillo 1/C
-
-
-
-
- - - - + +
- - - - - + + - - - - - - - - - +
TIRADAIMPRESIÓNIVATOTALUNIDAD + + +
+ + + + + +
+ ImprimeLibros ERP
+
C/ José Picón, 28 local A
+
+ 28028 + Madrid +
+
+34 910052574
+
+
100 uds.152,15€7,68€159,99€1,52€
+ + + +
+ +
+ + + + + + + - -
PRESUPUESTO Nº: 153153CLIENTE: JUAN JOSÉ + MÉNDEZFECHA: 10/10/2025
+ + + +
+ Título: + Libro de prueba +
+ + +
+
+
+
Encuadernación
+
Encuadernación:Fresado
+
Formato: + 148x210 mm +
+
Páginas:132
+
Páginas Negro:100
+
Páginas Color:32
+ +
+
Interior
+
Tipo de impresión:Color + Premium
+
Papel interior:Estucado + Mate +
+
Gramaje interior:115
+
+
+ +
+
+
Cubierta
+
Tipo de cubierta:Tapa + blanda +
+
Solapas:
+
Tamaño solapas:80 mm
+
Impresión:Una cara
+
Papel cubierta:Estucado + mate +
+
Gramaje cubierta:250
+
Acabado:Plastificado + Brillo 1/C
+
+ +
+
Servicios Extras
+ +
+
    +
  • + Ferro Digital + 0,00 € +
  • +
+
+ + +
+
Marcapáginas
+
Tamaño:50x210
+
Papel:Estucado + mate + 300 g
+
Impresión:Una cara +
+
Plastificado:Brillo + 1/C
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TIRADAIMPRESIÓNIVATOTALUNIDAD
100 uds.152,15€7,68€159,99€1,52€
Sin datos de tiradas.
+ +