netgescon-day0/app/Modules/StampeRate/Seeders/StampeRateSeeder.php

1640 lines
42 KiB
PHP

<?php
namespace App\Modules\StampeRate\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Carbon\Carbon;
/**
* Seeder per il modulo Stampe Rate Avanzate
*
* Popola le tabelle con:
* - Template di esempio
* - Configurazioni base
* - Dati di test (se ambiente di development)
*/
class StampeRateSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$this->seedTemplates();
$this->seedConfigurations();
// Solo in development, aggiungi dati di test
if (app()->environment('local', 'development')) {
$this->seedTestData();
}
}
/**
* Seed template di base
*/
private function seedTemplates(): void
{
$templates = [
[
'nome' => 'Template Rata Standard',
'descrizione' => 'Template base per la stampa delle rate condominiali',
'categoria' => 'rate_standard',
'html_content' => $this->getTemplateRataStandard(),
'css_content' => $this->getCssRataStandard(),
'variabili' => json_encode([
'condominio' => ['nome', 'indirizzo', 'codice_fiscale', 'amministratore', 'telefono', 'email'],
'proprietario' => ['nome', 'indirizzo', 'codice_fiscale', 'interno', 'millesimi'],
'rata' => ['numero', 'importo', 'scadenza', 'descrizione', 'periodo', 'note'],
'sistema' => ['data_stampa', 'numero_pagina', 'totale_pagine']
]),
'tags' => 'standard,base,rate,condominiali',
'status' => 'attivo',
'versione' => '1.0.0',
'is_pubblico' => true,
'created_by' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'nome' => 'Template Avviso Scadenza',
'descrizione' => 'Template per avvisi di pagamento in scadenza o scaduti',
'categoria' => 'avvisi',
'html_content' => $this->getTemplateAvvisoScadenza(),
'css_content' => $this->getCssAvvisoScadenza(),
'variabili' => json_encode([
'condominio' => ['nome', 'indirizzo', 'amministratore', 'telefono'],
'proprietario' => ['nome', 'indirizzo', 'interno'],
'rata' => ['numero', 'importo', 'scadenza', 'giorni_ritardo', 'interessi_mora'],
'avviso' => ['tipo', 'sollecito_numero', 'note_legali']
]),
'tags' => 'avviso,scadenza,solleciti,mora',
'status' => 'attivo',
'versione' => '1.0.0',
'is_pubblico' => true,
'created_by' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'nome' => 'Template Riepilogativo Annuale',
'descrizione' => 'Template per il riepilogo annuale dei pagamenti',
'categoria' => 'riepilogativo',
'html_content' => $this->getTemplateRiepilogativo(),
'css_content' => $this->getCssRiepilogativo(),
'variabili' => json_encode([
'condominio' => ['nome', 'indirizzo', 'amministratore'],
'proprietario' => ['nome', 'interno', 'millesimi'],
'riepilogo' => ['anno', 'totale_dovuto', 'totale_pagato', 'saldo', 'rate_pagate', 'rate_scadute'],
'dettaglio_rate' => ['lista_rate', 'pagamenti', 'saldi_mese']
]),
'tags' => 'riepilogo,annuale,saldo,pagamenti',
'status' => 'attivo',
'versione' => '1.0.0',
'is_pubblico' => true,
'created_by' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'nome' => 'Template Moderno Colorato',
'descrizione' => 'Template moderno con design colorato e professionale',
'categoria' => 'rate_personalizzate',
'html_content' => $this->getTemplateModerno(),
'css_content' => $this->getCssModerno(),
'variabili' => json_encode([
'condominio' => ['nome', 'indirizzo', 'logo_url'],
'proprietario' => ['nome', 'interno'],
'rata' => ['numero', 'importo', 'scadenza', 'descrizione'],
'design' => ['colore_primario', 'colore_secondario', 'font_family']
]),
'tags' => 'moderno,colorato,design,professionale',
'status' => 'attivo',
'versione' => '1.0.0',
'is_pubblico' => true,
'created_by' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'nome' => 'Template Minimale',
'descrizione' => 'Template essenziale e pulito per stampe veloci',
'categoria' => 'rate_standard',
'html_content' => $this->getTemplateMinimale(),
'css_content' => $this->getCssMinimale(),
'variabili' => json_encode([
'condominio' => ['nome'],
'proprietario' => ['nome', 'interno'],
'rata' => ['numero', 'importo', 'scadenza']
]),
'tags' => 'minimale,veloce,essenziale,semplice',
'status' => 'attivo',
'versione' => '1.0.0',
'is_pubblico' => true,
'created_by' => 1,
'created_at' => now(),
'updated_at' => now()
]
];
foreach ($templates as $template) {
DB::table('stampe_templates')->insert($template);
}
echo "✅ Creati " . count($templates) . " template di base\n";
}
/**
* Seed configurazioni modulo
*/
private function seedConfigurations(): void
{
$configurations = [
[
'chiave' => 'stampe_rate.pdf_engine',
'valore' => 'dompdf',
'tipo' => 'string',
'descrizione' => 'Engine per generazione PDF (dompdf, wkhtmltopdf, tcpdf)',
'is_public' => false
],
[
'chiave' => 'stampe_rate.default_font_size',
'valore' => '12',
'tipo' => 'number',
'descrizione' => 'Dimensione font di default per i PDF',
'is_public' => true
],
[
'chiave' => 'stampe_rate.default_paper_size',
'valore' => 'A4',
'tipo' => 'string',
'descrizione' => 'Formato carta di default (A4, A3, Letter)',
'is_public' => true
],
[
'chiave' => 'stampe_rate.logo_path',
'valore' => '/images/logo.png',
'tipo' => 'string',
'descrizione' => 'Percorso del logo aziendale',
'is_public' => true
],
[
'chiave' => 'stampe_rate.email_from_name',
'valore' => 'Amministratore Condominio',
'tipo' => 'string',
'descrizione' => 'Nome mittente per le email',
'is_public' => false
],
[
'chiave' => 'stampe_rate.email_from_address',
'valore' => 'admin@netgescon.local',
'tipo' => 'string',
'descrizione' => 'Indirizzo email mittente',
'is_public' => false
],
[
'chiave' => 'stampe_rate.auto_cleanup_days',
'valore' => '90',
'tipo' => 'number',
'descrizione' => 'Giorni dopo i quali eliminare automaticamente le stampe',
'is_public' => false
],
[
'chiave' => 'stampe_rate.max_file_size',
'valore' => '10485760',
'tipo' => 'number',
'descrizione' => 'Dimensione massima file in bytes (10MB)',
'is_public' => false
],
[
'chiave' => 'stampe_rate.email_tracking_enabled',
'valore' => 'true',
'tipo' => 'boolean',
'descrizione' => 'Abilita tracking aperture email',
'is_public' => false
],
[
'chiave' => 'stampe_rate.watermark_text',
'valore' => '',
'tipo' => 'string',
'descrizione' => 'Testo watermark sui PDF (vuoto = disabilitato)',
'is_public' => true
],
[
'chiave' => 'stampe_rate.default_template_id',
'valore' => '1',
'tipo' => 'number',
'descrizione' => 'ID del template di default',
'is_public' => true
],
[
'chiave' => 'stampe_rate.batch_email_limit',
'valore' => '50',
'tipo' => 'number',
'descrizione' => 'Limite invii email in batch',
'is_public' => false
],
[
'chiave' => 'stampe_rate.template_cache_enabled',
'valore' => 'true',
'tipo' => 'boolean',
'descrizione' => 'Abilita cache per i template compilati',
'is_public' => false
],
[
'chiave' => 'stampe_rate.pdf_compression',
'valore' => 'true',
'tipo' => 'boolean',
'descrizione' => 'Abilita compressione PDF',
'is_public' => true
],
[
'chiave' => 'stampe_rate.footer_text',
'valore' => 'Generato da NetGescon - Sistema di Gestione Condominiale',
'tipo' => 'string',
'descrizione' => 'Testo footer di default',
'is_public' => true
]
];
foreach ($configurations as $config) {
$config['updated_by'] = 1;
$config['created_at'] = now();
$config['updated_at'] = now();
DB::table('stampe_rate_config')->insert($config);
}
echo "✅ Create " . count($configurations) . " configurazioni base\n";
}
/**
* Seed dati di test (solo development)
*/
private function seedTestData(): void
{
// Crea alcune stampe di test
$stampeTest = [
[
'nome' => 'Test Stampa Rate Gennaio 2025',
'descrizione' => 'Stampa di test per le rate di gennaio',
'tipo_documento' => 'rata_multipla',
'status' => 'generata',
'template_id' => 1,
'stabile_id' => 1,
'rate_selezionate' => json_encode([1, 2, 3, 4, 5]),
'proprietari_selezionati' => json_encode([1, 2, 3, 4]),
'parametri_stampa' => json_encode([
'font_size' => 12,
'paper_size' => 'A4',
'margins' => ['top' => 20, 'bottom' => 20, 'left' => 15, 'right' => 15]
]),
'file_count' => 4,
'file_size_total' => 2048576,
'download_count' => 3,
'created_by' => 1,
'created_at' => now()->subDays(5),
'updated_at' => now()->subDays(5)
],
[
'nome' => 'Avvisi Scadenza Dicembre 2024',
'descrizione' => 'Avvisi per rate scadute di dicembre',
'tipo_documento' => 'avviso_scadenza',
'status' => 'inviata',
'template_id' => 2,
'stabile_id' => 1,
'rate_selezionate' => json_encode([10, 11]),
'proprietari_selezionati' => json_encode([2, 5]),
'email_abilitata' => true,
'email_subject' => 'Avviso pagamento in scadenza',
'email_inviate_count' => 2,
'email_aperte_count' => 1,
'file_count' => 2,
'created_by' => 1,
'created_at' => now()->subDays(10),
'updated_at' => now()->subDays(8)
]
];
foreach ($stampeTest as $stampa) {
DB::table('stampe_rate')->insert($stampa);
}
// Crea cronologia di test
$historyTest = [
[
'stampa_id' => 1,
'action' => 'created',
'dettagli' => 'Stampa creata dall\'utente admin',
'ip_address' => '127.0.0.1',
'created_by' => 1,
'created_at' => now()->subDays(5)
],
[
'stampa_id' => 1,
'action' => 'generated',
'dettagli' => 'PDF generati con successo (4 file)',
'ip_address' => '127.0.0.1',
'created_by' => 1,
'created_at' => now()->subDays(5)
],
[
'stampa_id' => 1,
'action' => 'downloaded',
'dettagli' => 'Download ZIP con tutti i file',
'ip_address' => '127.0.0.1',
'created_by' => 1,
'created_at' => now()->subDays(3)
],
[
'stampa_id' => 2,
'action' => 'created',
'dettagli' => 'Avviso scadenza creato',
'ip_address' => '127.0.0.1',
'created_by' => 1,
'created_at' => now()->subDays(10)
],
[
'stampa_id' => 2,
'action' => 'sent',
'dettagli' => 'Email inviate a 2 destinatari',
'ip_address' => '127.0.0.1',
'created_by' => 1,
'created_at' => now()->subDays(8)
]
];
foreach ($historyTest as $history) {
DB::table('stampe_rate_history')->insert($history);
}
// Crea log email di test
$emailTest = [
[
'stampa_id' => 2,
'tracking_id' => (string) Str::uuid(),
'unsubscribe_token' => Str::random(32),
'recipient_email' => 'proprietario1@example.com',
'recipient_name' => 'Mario Rossi',
'recipient_type' => 'proprietario',
'proprietario_id' => 2,
'subject' => 'Avviso pagamento in scadenza - Condominio Via Roma',
'body_html' => '<p>Gentile proprietario, la informiamo che...</p>',
'status' => 'sent',
'sent_at' => now()->subDays(8),
'opened_at' => now()->subDays(7),
'opened_count' => 2,
'opened_ip' => '192.168.1.100',
'sent_by' => 1,
'created_at' => now()->subDays(8),
'updated_at' => now()->subDays(7)
],
[
'stampa_id' => 2,
'tracking_id' => (string) Str::uuid(),
'unsubscribe_token' => Str::random(32),
'recipient_email' => 'proprietario2@example.com',
'recipient_name' => 'Giuseppe Verdi',
'recipient_type' => 'proprietario',
'proprietario_id' => 5,
'subject' => 'Avviso pagamento in scadenza - Condominio Via Roma',
'body_html' => '<p>Gentile proprietario, la informiamo che...</p>',
'status' => 'sent',
'sent_at' => now()->subDays(8),
'sent_by' => 1,
'created_at' => now()->subDays(8),
'updated_at' => now()->subDays(8)
]
];
foreach ($emailTest as $email) {
DB::table('stampe_rate_email_log')->insert($email);
}
echo "✅ Creati dati di test per il modulo\n";
}
// Template HTML/CSS
private function getTemplateRataStandard(): string
{
return '<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Rata Condominiale</title>
</head>
<body>
<div class="header">
<div class="logo">
{{#if condominio.logo_url}}
<img src="{{condominio.logo_url}}" alt="Logo" />
{{/if}}
</div>
<div class="condominio-info">
<h1>{{condominio.nome}}</h1>
<p>{{condominio.indirizzo}}</p>
<p>C.F. {{condominio.codice_fiscale}}</p>
{{#if condominio.amministratore}}
<p>Amministratore: {{condominio.amministratore}}</p>
{{/if}}
</div>
</div>
<div class="destinatario">
<h3>Spett.le</h3>
<p><strong>{{proprietario.nome}}</strong></p>
<p>{{proprietario.indirizzo}}</p>
<p>Interno: {{proprietario.interno}}</p>
{{#if proprietario.codice_fiscale}}
<p>C.F. {{proprietario.codice_fiscale}}</p>
{{/if}}
</div>
<div class="rata-info">
<h2>RATA CONDOMINIALE N. {{rata.numero}}</h2>
<div class="rata-dettagli">
<div class="rata-campo">
<span class="label">Periodo:</span>
<span class="value">{{rata.periodo}}</span>
</div>
<div class="rata-campo">
<span class="label">Scadenza:</span>
<span class="value important">{{rata.scadenza}}</span>
</div>
<div class="rata-campo">
<span class="label">Importo:</span>
<span class="value important">€ {{rata.importo}}</span>
</div>
{{#if proprietario.millesimi}}
<div class="rata-campo">
<span class="label">Millesimi:</span>
<span class="value">{{proprietario.millesimi}}</span>
</div>
{{/if}}
</div>
</div>
{{#if rata.descrizione}}
<div class="descrizione">
<h3>Descrizione</h3>
<p>{{rata.descrizione}}</p>
</div>
{{/if}}
{{#if rata.note}}
<div class="note">
<h3>Note</h3>
<p>{{rata.note}}</p>
</div>
{{/if}}
<div class="footer">
<p>Documento generato il {{sistema.data_stampa}}</p>
{{#if condominio.telefono}}
<p>Per informazioni: {{condominio.telefono}} - {{condominio.email}}</p>
{{/if}}
</div>
</body>
</html>';
}
private function getCssRataStandard(): string
{
return 'body {
font-family: Arial, sans-serif;
font-size: 11pt;
line-height: 1.4;
margin: 0;
padding: 20px;
color: #333;
}
.header {
display: flex;
justify-content: space-between;
align-items: flex-start;
border-bottom: 2px solid #333;
padding-bottom: 15px;
margin-bottom: 20px;
}
.logo img {
max-height: 60px;
max-width: 120px;
}
.condominio-info {
text-align: right;
flex: 1;
margin-left: 20px;
}
.condominio-info h1 {
margin: 0 0 10px 0;
font-size: 16pt;
color: #2c3e50;
}
.condominio-info p {
margin: 3px 0;
font-size: 9pt;
}
.destinatario {
margin: 30px 0;
padding: 15px;
background-color: #f8f9fa;
border-left: 4px solid #3498db;
}
.destinatario h3 {
margin: 0 0 10px 0;
font-size: 12pt;
}
.destinatario p {
margin: 5px 0;
}
.rata-info {
margin: 30px 0;
text-align: center;
}
.rata-info h2 {
font-size: 18pt;
color: #2c3e50;
border: 2px solid #3498db;
padding: 15px;
margin-bottom: 20px;
background-color: #ecf0f1;
}
.rata-dettagli {
display: table;
width: 100%;
border-collapse: collapse;
}
.rata-campo {
display: table-row;
}
.rata-campo .label,
.rata-campo .value {
display: table-cell;
padding: 8px 15px;
border: 1px solid #bdc3c7;
}
.rata-campo .label {
background-color: #ecf0f1;
font-weight: bold;
width: 40%;
}
.rata-campo .value {
text-align: right;
}
.rata-campo .value.important {
font-weight: bold;
font-size: 12pt;
color: #e74c3c;
}
.descrizione,
.note {
margin: 20px 0;
padding: 15px;
background-color: #f8f9fa;
border-radius: 5px;
}
.descrizione h3,
.note h3 {
margin: 0 0 10px 0;
font-size: 12pt;
color: #2c3e50;
}
.footer {
margin-top: 40px;
padding-top: 15px;
border-top: 1px solid #bdc3c7;
text-align: center;
font-size: 9pt;
color: #7f8c8d;
}
.footer p {
margin: 5px 0;
}';
}
private function getTemplateAvvisoScadenza(): string
{
return '<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Avviso di Pagamento</title>
</head>
<body>
<div class="header urgente">
<div class="avviso-tipo">
<h1>⚠️ AVVISO DI PAGAMENTO</h1>
<p class="sottotitolo">{{avviso.tipo}}</p>
</div>
<div class="condominio-info">
<h2>{{condominio.nome}}</h2>
<p>{{condominio.indirizzo}}</p>
</div>
</div>
<div class="destinatario">
<p><strong>Alla cortese attenzione di:</strong></p>
<p class="nome-destinatario">{{proprietario.nome}}</p>
<p>{{proprietario.indirizzo}}</p>
<p>Interno: {{proprietario.interno}}</p>
</div>
<div class="messaggio-principale">
<p>Con la presente La informiamo che risulta <strong>non ancora pervenuto</strong> il pagamento della seguente rata condominiale:</p>
</div>
<div class="rata-scaduta">
<h3>DETTAGLI RATA SCADUTA</h3>
<div class="rata-box">
<div class="rata-numero">Rata N. {{rata.numero}}</div>
<div class="rata-importo">€ {{rata.importo}}</div>
<div class="rata-scadenza">Scadenza: {{rata.scadenza}}</div>
{{#if rata.giorni_ritardo}}
<div class="giorni-ritardo">Ritardo: {{rata.giorni_ritardo}} giorni</div>
{{/if}}
</div>
{{#if rata.interessi_mora}}
<div class="mora-info">
<p><strong>Interessi di mora maturati:</strong> € {{rata.interessi_mora}}</p>
</div>
{{/if}}
</div>
<div class="istruzioni-pagamento">
<h3>🏦 MODALITÀ DI PAGAMENTO</h3>
<p>Il pagamento dovrà essere effettuato <strong>entro 15 giorni</strong> dal ricevimento del presente avviso.</p>
<p>Per informazioni sui metodi di pagamento, contattare l\'amministratore.</p>
</div>
{{#if avviso.note_legali}}
<div class="note-legali">
<h3>⚖️ NOTE LEGALI</h3>
<p>{{avviso.note_legali}}</p>
</div>
{{/if}}
<div class="contatti">
<h3>📞 CONTATTI AMMINISTRATORE</h3>
<p><strong>{{condominio.amministratore}}</strong></p>
<p>Tel: {{condominio.telefono}}</p>
</div>
<div class="footer">
<p>Documento generato automaticamente il {{sistema.data_stampa}}</p>
{{#if avviso.sollecito_numero}}
<p>Sollecito n. {{avviso.sollecito_numero}}</p>
{{/if}}
</div>
</body>
</html>';
}
private function getCssAvvisoScadenza(): string
{
return 'body {
font-family: Arial, sans-serif;
font-size: 11pt;
line-height: 1.5;
margin: 0;
padding: 20px;
color: #2c3e50;
}
.header.urgente {
background: linear-gradient(135deg, #e74c3c, #c0392b);
color: white;
padding: 20px;
border-radius: 10px;
text-align: center;
margin-bottom: 30px;
}
.header.urgente h1 {
font-size: 22pt;
margin: 0 0 10px 0;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.sottotitolo {
font-size: 14pt;
font-weight: bold;
margin: 10px 0;
}
.condominio-info h2 {
font-size: 16pt;
margin: 10px 0 5px 0;
}
.destinatario {
background-color: #ecf0f1;
padding: 20px;
border-left: 5px solid #e74c3c;
margin: 20px 0;
}
.nome-destinatario {
font-size: 14pt;
font-weight: bold;
color: #e74c3c;
margin: 10px 0;
}
.messaggio-principale {
background-color: #fff3cd;
border: 1px solid #ffeaa7;
padding: 20px;
border-radius: 5px;
margin: 30px 0;
text-align: center;
font-size: 12pt;
}
.rata-scaduta {
background-color: #f8d7da;
border: 2px solid #e74c3c;
border-radius: 10px;
padding: 25px;
margin: 30px 0;
text-align: center;
}
.rata-scaduta h3 {
color: #e74c3c;
font-size: 16pt;
margin: 0 0 20px 0;
text-transform: uppercase;
}
.rata-box {
background-color: white;
border-radius: 8px;
padding: 20px;
margin: 15px 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.rata-numero {
font-size: 14pt;
font-weight: bold;
color: #2c3e50;
margin-bottom: 10px;
}
.rata-importo {
font-size: 24pt;
font-weight: bold;
color: #e74c3c;
margin: 15px 0;
}
.rata-scadenza {
font-size: 12pt;
color: #34495e;
margin: 10px 0;
}
.giorni-ritardo {
background-color: #e74c3c;
color: white;
padding: 8px 15px;
border-radius: 20px;
display: inline-block;
font-weight: bold;
margin-top: 10px;
}
.mora-info {
background-color: #fff;
border: 1px solid #e74c3c;
padding: 15px;
border-radius: 5px;
margin-top: 15px;
}
.mora-info p {
margin: 0;
font-size: 12pt;
color: #e74c3c;
}
.istruzioni-pagamento {
background-color: #d4edda;
border: 1px solid #c3e6cb;
border-radius: 5px;
padding: 20px;
margin: 30px 0;
}
.istruzioni-pagamento h3 {
color: #155724;
font-size: 14pt;
margin: 0 0 15px 0;
}
.note-legali {
background-color: #f8f9fa;
border-left: 4px solid #6c757d;
padding: 20px;
margin: 30px 0;
}
.note-legali h3 {
color: #495057;
font-size: 12pt;
margin: 0 0 15px 0;
}
.contatti {
background-color: #e3f2fd;
border: 1px solid #2196f3;
border-radius: 5px;
padding: 20px;
margin: 30px 0;
}
.contatti h3 {
color: #1976d2;
font-size: 14pt;
margin: 0 0 15px 0;
}
.footer {
border-top: 2px solid #bdc3c7;
padding-top: 20px;
margin-top: 40px;
text-align: center;
font-size: 9pt;
color: #7f8c8d;
}
.footer p {
margin: 5px 0;
}';
}
private function getTemplateRiepilogativo(): string
{
return '<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Riepilogo Annuale</title>
</head>
<body>
<div class="header">
<h1>RIEPILOGO ANNUALE {{riepilogo.anno}}</h1>
<div class="condominio">
<h2>{{condominio.nome}}</h2>
<p>{{condominio.indirizzo}}</p>
</div>
</div>
<div class="proprietario-info">
<h3>Proprietario</h3>
<p><strong>{{proprietario.nome}}</strong></p>
<p>Interno: {{proprietario.interno}} - Millesimi: {{proprietario.millesimi}}</p>
</div>
<div class="riepilogo-generale">
<h3>📊 RIEPILOGO GENERALE</h3>
<div class="stats-grid">
<div class="stat-box">
<div class="stat-label">Totale Dovuto</div>
<div class="stat-value">€ {{riepilogo.totale_dovuto}}</div>
</div>
<div class="stat-box">
<div class="stat-label">Totale Pagato</div>
<div class="stat-value paid">€ {{riepilogo.totale_pagato}}</div>
</div>
<div class="stat-box">
<div class="stat-label">Saldo</div>
<div class="stat-value {{#if riepilogo.saldo_negativo}}negative{{else}}positive{{/if}}">
€ {{riepilogo.saldo}}
</div>
</div>
</div>
<div class="stats-grid">
<div class="stat-box">
<div class="stat-label">Rate Pagate</div>
<div class="stat-value">{{riepilogo.rate_pagate}}</div>
</div>
<div class="stat-box">
<div class="stat-label">Rate Scadute</div>
<div class="stat-value negative">{{riepilogo.rate_scadute}}</div>
</div>
</div>
</div>
<div class="dettaglio-rate">
<h3>📋 DETTAGLIO RATE</h3>
<table>
<thead>
<tr>
<th>Mese</th>
<th>N. Rata</th>
<th>Importo</th>
<th>Scadenza</th>
<th>Pagamento</th>
<th>Stato</th>
</tr>
</thead>
<tbody>
{{#each dettaglio_rate.lista_rate}}
<tr class="{{status_class}}">
<td>{{mese}}</td>
<td>{{numero}}</td>
<td>€ {{importo}}</td>
<td>{{scadenza}}</td>
<td>{{data_pagamento}}</td>
<td>
<span class="status-badge {{status_class}}">{{status_text}}</span>
</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
{{#if dettaglio_rate.pagamenti}}
<div class="pagamenti-effettuati">
<h3>💳 PAGAMENTI EFFETTUATI</h3>
<table>
<thead>
<tr>
<th>Data</th>
<th>Importo</th>
<th>Modalità</th>
<th>Riferimento</th>
</tr>
</thead>
<tbody>
{{#each dettaglio_rate.pagamenti}}
<tr>
<td>{{data}}</td>
<td>€ {{importo}}</td>
<td>{{modalita}}</td>
<td>{{riferimento}}</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
{{/if}}
<div class="footer">
<p>Documento generato il {{sistema.data_stampa}}</p>
<p>Per ulteriori informazioni contattare: {{condominio.amministratore}}</p>
</div>
</body>
</html>';
}
private function getCssRiepilogativo(): string
{
return 'body {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
font-size: 10pt;
line-height: 1.4;
margin: 0;
padding: 15px;
color: #2c3e50;
}
.header {
text-align: center;
margin-bottom: 30px;
border-bottom: 3px solid #3498db;
padding-bottom: 20px;
}
.header h1 {
font-size: 24pt;
color: #2c3e50;
margin: 0 0 15px 0;
text-transform: uppercase;
letter-spacing: 1px;
}
.condominio h2 {
font-size: 16pt;
color: #3498db;
margin: 10px 0 5px 0;
}
.proprietario-info {
background: linear-gradient(135deg, #f8f9fa, #e9ecef);
padding: 20px;
border-radius: 8px;
margin: 20px 0;
border-left: 5px solid #3498db;
}
.proprietario-info h3 {
margin: 0 0 10px 0;
color: #2c3e50;
font-size: 12pt;
}
.riepilogo-generale {
margin: 30px 0;
}
.riepilogo-generale h3 {
font-size: 14pt;
color: #2c3e50;
margin: 0 0 20px 0;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
margin: 20px 0;
}
.stat-box {
background: white;
border: 1px solid #e1e8ed;
border-radius: 8px;
padding: 15px;
text-align: center;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.stat-label {
font-size: 9pt;
color: #7f8c8d;
margin-bottom: 8px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.stat-value {
font-size: 16pt;
font-weight: bold;
color: #2c3e50;
}
.stat-value.paid {
color: #27ae60;
}
.stat-value.positive {
color: #27ae60;
}
.stat-value.negative {
color: #e74c3c;
}
.dettaglio-rate,
.pagamenti-effettuati {
margin: 30px 0;
}
.dettaglio-rate h3,
.pagamenti-effettuati h3 {
font-size: 14pt;
color: #2c3e50;
margin: 0 0 15px 0;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
thead th {
background-color: #34495e;
color: white;
padding: 12px 8px;
font-size: 9pt;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.5px;
}
tbody td {
padding: 10px 8px;
border-bottom: 1px solid #ecf0f1;
font-size: 9pt;
}
tbody tr:hover {
background-color: #f8f9fa;
}
tbody tr.pagata {
background-color: #d5f4e6;
}
tbody tr.scaduta {
background-color: #ffeaa7;
}
tbody tr.non-pagata {
background-color: #fab1a0;
}
.status-badge {
padding: 4px 8px;
border-radius: 12px;
font-size: 8pt;
font-weight: bold;
text-transform: uppercase;
}
.status-badge.pagata {
background-color: #27ae60;
color: white;
}
.status-badge.scaduta {
background-color: #f39c12;
color: white;
}
.status-badge.non-pagata {
background-color: #e74c3c;
color: white;
}
.footer {
margin-top: 40px;
padding-top: 20px;
border-top: 2px solid #ecf0f1;
text-align: center;
font-size: 8pt;
color: #7f8c8d;
}
.footer p {
margin: 5px 0;
}
@media print {
body { padding: 10px; }
.stat-box { break-inside: avoid; }
table { page-break-inside: auto; }
tr { page-break-inside: avoid; }
}';
}
private function getTemplateModerno(): string
{
return '<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Rata Condominiale - Design Moderno</title>
</head>
<body>
<div class="container">
<div class="header-modern">
<div class="brand-section">
{{#if condominio.logo_url}}
<img src="{{condominio.logo_url}}" alt="Logo" class="logo-modern"/>
{{/if}}
<div class="brand-text">
<h1>{{condominio.nome}}</h1>
<p class="address">{{condominio.indirizzo}}</p>
</div>
</div>
<div class="document-type">
<span class="type-badge">RATA CONDOMINIALE</span>
</div>
</div>
<div class="content-grid">
<div class="left-panel">
<div class="card destinatario-card">
<div class="card-header">
<h3>👤 Destinatario</h3>
</div>
<div class="card-body">
<p class="recipient-name">{{proprietario.nome}}</p>
<p class="recipient-detail">Interno {{proprietario.interno}}</p>
</div>
</div>
<div class="card info-card">
<div class="card-header">
<h3>📋 Dettagli</h3>
</div>
<div class="card-body">
<div class="info-row">
<span class="info-label">Rata N.</span>
<span class="info-value">{{rata.numero}}</span>
</div>
<div class="info-row">
<span class="info-label">Scadenza</span>
<span class="info-value highlight">{{rata.scadenza}}</span>
</div>
{{#if proprietario.millesimi}}
<div class="info-row">
<span class="info-label">Millesimi</span>
<span class="info-value">{{proprietario.millesimi}}</span>
</div>
{{/if}}
</div>
</div>
</div>
<div class="right-panel">
<div class="amount-showcase">
<div class="amount-label">Importo da Pagare</div>
<div class="amount-value">€ {{rata.importo}}</div>
<div class="amount-sublabel">Scadenza: {{rata.scadenza}}</div>
</div>
{{#if rata.descrizione}}
<div class="description-box">
<h4>📝 Descrizione</h4>
<p>{{rata.descrizione}}</p>
</div>
{{/if}}
</div>
</div>
<div class="footer-modern">
<div class="footer-left">
<p>Documento generato il {{sistema.data_stamina}}</p>
</div>
<div class="footer-right">
<p>NetGescon - Sistema di Gestione Condominiale</p>
</div>
</div>
</div>
</body>
</html>';
}
private function getCssModerno(): string
{
return 'body {
font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
margin: 0;
padding: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: #2d3748;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
min-height: 100vh;
box-shadow: 0 20px 60px rgba(0,0,0,0.1);
}
.header-modern {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
padding: 30px;
display: flex;
justify-content: space-between;
align-items: center;
}
.brand-section {
display: flex;
align-items: center;
gap: 20px;
}
.logo-modern {
width: 60px;
height: 60px;
border-radius: 50%;
object-fit: cover;
border: 3px solid rgba(255,255,255,0.3);
}
.brand-text h1 {
font-size: 24pt;
font-weight: 700;
margin: 0;
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.address {
font-size: 11pt;
opacity: 0.9;
margin: 5px 0 0 0;
}
.type-badge {
background: rgba(255,255,255,0.2);
padding: 8px 16px;
border-radius: 20px;
font-size: 10pt;
font-weight: 600;
letter-spacing: 1px;
backdrop-filter: blur(10px);
}
.content-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
padding: 40px 30px;
}
.card {
background: white;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
border: 1px solid #e2e8f0;
margin-bottom: 20px;
overflow: hidden;
}
.card-header {
background: linear-gradient(135deg, #f7fafc, #edf2f7);
padding: 15px 20px;
border-bottom: 1px solid #e2e8f0;
}
.card-header h3 {
margin: 0;
font-size: 12pt;
color: #4a5568;
font-weight: 600;
}
.card-body {
padding: 20px;
}
.recipient-name {
font-size: 16pt;
font-weight: 700;
color: #2d3748;
margin: 0 0 8px 0;
}
.recipient-detail {
color: #718096;
margin: 0;
font-size: 11pt;
}
.info-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
border-bottom: 1px solid #f7fafc;
}
.info-row:last-child {
border-bottom: none;
}
.info-label {
font-size: 10pt;
color: #718096;
font-weight: 500;
}
.info-value {
font-size: 11pt;
font-weight: 600;
color: #2d3748;
}
.info-value.highlight {
color: #e53e3e;
font-weight: 700;
}
.amount-showcase {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
padding: 30px;
border-radius: 16px;
text-align: center;
margin-bottom: 25px;
position: relative;
overflow: hidden;
}
.amount-showcase::before {
content: "";
position: absolute;
top: -50%;
right: -50%;
width: 100%;
height: 100%;
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
transform: rotate(45deg);
}
.amount-label {
font-size: 11pt;
opacity: 0.9;
margin-bottom: 10px;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 500;
}
.amount-value {
font-size: 36pt;
font-weight: 800;
margin: 10px 0;
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.amount-sublabel {
font-size: 10pt;
opacity: 0.8;
}
.description-box {
background: #f7fafc;
border-left: 4px solid #4facfe;
padding: 20px;
border-radius: 0 8px 8px 0;
}
.description-box h4 {
margin: 0 0 12px 0;
font-size: 11pt;
color: #4a5568;
font-weight: 600;
}
.description-box p {
margin: 0;
line-height: 1.6;
color: #2d3748;
font-size: 10pt;
}
.footer-modern {
background: #f7fafc;
padding: 20px 30px;
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid #e2e8f0;
font-size: 9pt;
color: #718096;
}
.footer-left p,
.footer-right p {
margin: 0;
}
@media print {
body {
background: white;
}
.container {
box-shadow: none;
}
.content-grid {
grid-template-columns: 1fr 1fr;
gap: 20px;
padding: 20px;
}
}';
}
private function getTemplateMinimale(): string
{
return '<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Rata - {{rata.numero}}</title>
</head>
<body>
<div class="header-minimal">
<h1>{{condominio.nome}}</h1>
<h2>RATA N. {{rata.numero}}</h2>
</div>
<div class="content-minimal">
<div class="recipient">
<strong>{{proprietario.nome}}</strong><br>
Interno: {{proprietario.interno}}
</div>
<div class="amount-section">
<div class="amount">€ {{rata.importo}}</div>
<div class="due-date">Scadenza: {{rata.scadenza}}</div>
</div>
</div>
<div class="footer-minimal">
Generato il {{sistema.data_stampa}}
</div>
</body>
</html>';
}
private function getCssMinimale(): string
{
return 'body {
font-family: Arial, sans-serif;
font-size: 12pt;
margin: 20px;
color: #333;
line-height: 1.4;
}
.header-minimal {
text-align: center;
border-bottom: 2px solid #333;
padding-bottom: 15px;
margin-bottom: 30px;
}
.header-minimal h1 {
font-size: 18pt;
margin: 0 0 10px 0;
}
.header-minimal h2 {
font-size: 16pt;
margin: 0;
color: #666;
}
.content-minimal {
display: flex;
justify-content: space-between;
align-items: center;
margin: 40px 0;
}
.recipient {
font-size: 14pt;
}
.amount-section {
text-align: right;
}
.amount {
font-size: 24pt;
font-weight: bold;
color: #e74c3c;
margin-bottom: 5px;
}
.due-date {
font-size: 11pt;
color: #666;
}
.footer-minimal {
text-align: center;
font-size: 9pt;
color: #999;
border-top: 1px solid #ccc;
padding-top: 15px;
margin-top: 50px;
}';
}
}