690 lines
27 KiB
PHP
Executable File
690 lines
27 KiB
PHP
Executable File
<?php
|
|
namespace App\Filament\Pages\Gescon;
|
|
|
|
use App\Models\FatturaElettronica;
|
|
use App\Models\Preventivo;
|
|
use App\Models\TabellaMillesimale;
|
|
use App\Models\User;
|
|
use App\Models\VocePreventivo;
|
|
use App\Models\VoceSpesa;
|
|
use App\Services\FattureElettroniche\FatturaElettronicaXmlParser;
|
|
use App\Services\RipartizioneSpesaService;
|
|
use App\Support\ModuleVisibility;
|
|
use App\Support\StabileContext;
|
|
use BackedEnum;
|
|
use Filament\Forms\Components\Placeholder;
|
|
use Filament\Forms\Components\Select;
|
|
use Filament\Forms\Components\TextInput;
|
|
use Filament\Forms\Concerns\InteractsWithForms;
|
|
use Filament\Forms\Contracts\HasForms;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Filament\Schemas\Components\Grid;
|
|
use Filament\Schemas\Components\Section;
|
|
use Filament\Schemas\Schema;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\DB;
|
|
use UnitEnum;
|
|
|
|
class RegistrazioneUnificata extends Page implements HasForms
|
|
{
|
|
use InteractsWithForms;
|
|
|
|
protected static bool $shouldRegisterNavigation = false;
|
|
|
|
protected static ?string $navigationLabel = 'Registrazione unificata';
|
|
|
|
protected static ?string $title = 'Registrazione unificata';
|
|
|
|
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-pencil-square';
|
|
|
|
protected static UnitEnum|string|null $navigationGroup = 'GESCON';
|
|
|
|
protected static ?int $navigationSort = 21;
|
|
|
|
protected static ?string $slug = 'gescon/ordinarie/registrazione-unificata';
|
|
|
|
protected string $view = 'filament.pages.gescon.registrazione-unificata';
|
|
|
|
public ?\App\Models\Stabile $stabileAttivo = null;
|
|
|
|
public array $data = [];
|
|
|
|
public static function canAccess() : bool
|
|
{
|
|
$user = Auth::user();
|
|
|
|
if (! ModuleVisibility::canAccessGesconInternal($user, ['super-admin', 'admin', 'amministratore'])) {
|
|
return false;
|
|
}
|
|
|
|
if ($user->hasAnyRole(['super-admin', 'admin'])) {
|
|
return true;
|
|
}
|
|
|
|
return $user->can('contabilita.gestioni');
|
|
}
|
|
|
|
public function mount(): void
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return;
|
|
}
|
|
|
|
$activeId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $activeId) {
|
|
$this->stabileAttivo = null;
|
|
return;
|
|
}
|
|
|
|
$this->stabileAttivo = StabileContext::accessibleStabili($user)
|
|
->firstWhere('id', $activeId);
|
|
|
|
$this->getSchema('form')?->fill([
|
|
'tipo_spesa' => 'singola',
|
|
'anno_gestione' => (int) now()->format('Y'),
|
|
]);
|
|
}
|
|
|
|
public function form(Schema $schema): Schema
|
|
{
|
|
return $schema
|
|
->statePath('data')
|
|
->components($this->getFormSchema());
|
|
}
|
|
|
|
protected function getFormSchema(): array
|
|
{
|
|
return [
|
|
Grid::make(3)->schema([
|
|
Section::make('Registrazione')
|
|
->columnSpan(2)
|
|
->schema([
|
|
Select::make('tipo_spesa')
|
|
->label('Tipo')
|
|
->options([
|
|
'singola' => 'Spesa singola',
|
|
'aggregata' => 'Acqua / Riscaldamento (aggregata)',
|
|
])
|
|
->required()
|
|
->live(),
|
|
|
|
Select::make('legacy_voce_id')
|
|
->label('Voce (GESCON)')
|
|
->options([])
|
|
->searchable()
|
|
->getSearchResultsUsing(fn(string $search): array=> $this->searchLegacyVoci($search))
|
|
->getOptionLabelUsing(fn($value): ?string => $this->getLegacyVoceLabel($value))
|
|
->live()
|
|
->afterStateUpdated(function ($state): void {
|
|
if (! $state) {
|
|
return;
|
|
}
|
|
$this->loadLegacyVoce((int) $state);
|
|
})
|
|
->required(),
|
|
|
|
Grid::make(3)->schema([
|
|
Placeholder::make('legacy_tabella')
|
|
->label('Tabella')
|
|
->content(fn(callable $get) => $get('legacy_tabella') ?: '—'),
|
|
Placeholder::make('legacy_prev_euro')
|
|
->label('Prev. (€)')
|
|
->content(fn(callable $get) => is_numeric($get('legacy_prev_euro')) ? number_format((float) $get('legacy_prev_euro'), 2, ',', '.') : '—'),
|
|
Placeholder::make('legacy_cons_euro')
|
|
->label('Cons. (€)')
|
|
->content(fn(callable $get) => is_numeric($get('legacy_cons_euro')) ? number_format((float) $get('legacy_cons_euro'), 2, ',', '.') : '—'),
|
|
]),
|
|
|
|
Select::make('tabella_millesimale_id')
|
|
->label('Tabella millesimale')
|
|
->options(fn() => $this->getTabelleOptions())
|
|
->searchable()
|
|
->required(),
|
|
|
|
TextInput::make('descrizione')
|
|
->label('Descrizione')
|
|
->maxLength(255)
|
|
->required(),
|
|
|
|
Grid::make(2)->schema([
|
|
TextInput::make('anno_gestione')
|
|
->label('Anno gestione')
|
|
->numeric()
|
|
->required(),
|
|
TextInput::make('importo_consuntivo')
|
|
->label('Importo consuntivo (€)')
|
|
->numeric()
|
|
->required(),
|
|
]),
|
|
]),
|
|
|
|
Section::make('Fattura elettronica (XML)')
|
|
->columnSpan(1)
|
|
->schema([
|
|
Select::make('fattura_elettronica_id')
|
|
->label('Seleziona fattura')
|
|
->options(fn() => $this->getFattureOptions())
|
|
->searchable()
|
|
->visible(fn(callable $get) => $get('tipo_spesa') === 'singola')
|
|
->live(),
|
|
|
|
Select::make('fatture_elettroniche_ids')
|
|
->label('Seleziona fatture (multiple)')
|
|
->options(fn() => $this->getFattureOptions())
|
|
->searchable()
|
|
->multiple()
|
|
->visible(fn(callable $get) => $get('tipo_spesa') === 'aggregata')
|
|
->live(),
|
|
|
|
Placeholder::make('xml_preview_supplier')
|
|
->label('Fornitore')
|
|
->content(fn(callable $get) => $get('fornitore_id') ? (string) ($this->getFornitoreDenominazione((int) $get('fornitore_id')) ?: '—'): '—'),
|
|
Placeholder::make('xml_preview_doc')
|
|
->label('Documento')
|
|
->content(fn(callable $get) => trim(((string) ($get('numero_documento') ?: '—')) . ' • ' . ((string) ($get('data_documento') ?: '—')))),
|
|
Placeholder::make('xml_preview_totale')
|
|
->label('Totale')
|
|
->content(fn(callable $get) => is_numeric($get('totale')) ? number_format((float) $get('totale'), 2, ',', '.') . ' €' : '—'),
|
|
Placeholder::make('xml_preview_pagamento')
|
|
->label('Pagamento')
|
|
->content(fn(callable $get) => trim(((string) ($get('modalita_pagamento') ?: '—')) . ' • ' . ((string) ($get('iban') ?: '—')))),
|
|
Placeholder::make('xml_preview_consumo')
|
|
->label('Consumo/contatore')
|
|
->content(function (callable $get) {
|
|
$val = $get('consumo_valore');
|
|
$rif = $get('consumo_riferimento');
|
|
if (! is_numeric($val) && ! $rif) {
|
|
return '—';
|
|
}
|
|
$a = is_numeric($val) ? (string) $val : '';
|
|
$b = (string) ($get('consumo_unita') ?: '');
|
|
$c = (string) ($rif ?: '');
|
|
return trim(trim($a . ' ' . $b) . ' ' . $c);
|
|
}),
|
|
]),
|
|
]),
|
|
];
|
|
}
|
|
|
|
public function applyXml(): void
|
|
{
|
|
if (! $this->stabileAttivo) {
|
|
Notification::make()->title('Seleziona uno stabile')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$state = $this->getSchema('form')?->getState() ?? [];
|
|
$fatture = $this->getSelectedFatture($state);
|
|
if ($fatture->isEmpty()) {
|
|
Notification::make()->title('Seleziona una fattura XML')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$totale = (float) $fatture->sum('totale');
|
|
$imponibile = (float) $fatture->sum('imponibile');
|
|
$iva = (float) $fatture->sum('iva');
|
|
|
|
$first = $fatture->first();
|
|
if (! $first instanceof FatturaElettronica) {
|
|
return;
|
|
}
|
|
|
|
$data = $this->getParsedOrStoredXmlData($first);
|
|
|
|
$fornitoreId = $first->fornitore_id;
|
|
$numero = $first->numero_fattura;
|
|
$dataDoc = optional($first->data_fattura)->format('Y-m-d');
|
|
|
|
$descr = (string) ($state['descrizione'] ?? '');
|
|
if ($descr === '') {
|
|
$descr = trim('Fattura ' . ($numero ?: '') . ' ' . ($fornitoreId ? ($this->getFornitoreDenominazione((int) $fornitoreId) ?: ''): ''));
|
|
}
|
|
|
|
$this->getSchema('form')?->fill([
|
|
'fornitore_id' => $fornitoreId,
|
|
'numero_documento' => $numero,
|
|
'data_documento' => $dataDoc,
|
|
'data_scadenza' => optional($first->data_scadenza)->format('Y-m-d'),
|
|
'modalita_pagamento' => $data['pagamento_modalita'] ?? null,
|
|
'iban' => $data['pagamento_iban'] ?? null,
|
|
'bic' => $data['pagamento_bic'] ?? null,
|
|
'imponibile' => $imponibile,
|
|
'iva' => $iva,
|
|
'totale' => $totale,
|
|
'importo_consuntivo' => $totale,
|
|
'consumo_valore' => isset($data['consumo_valore']) && is_numeric($data['consumo_valore']) ? (float) $data['consumo_valore'] : null,
|
|
'consumo_unita' => $data['consumo_unita'] ?? null,
|
|
'consumo_riferimento' => $data['consumo_riferimento'] ?? null,
|
|
'descrizione' => $descr,
|
|
]);
|
|
|
|
Notification::make()->title('Dati XML applicati')->success()->send();
|
|
}
|
|
|
|
public function creaRegistrazione(): void
|
|
{
|
|
if (! $this->stabileAttivo) {
|
|
Notification::make()->title('Seleziona uno stabile')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$state = $this->getSchema('form')?->getState() ?? [];
|
|
validator($state, [
|
|
'tipo_spesa' => 'required|in:singola,aggregata',
|
|
'legacy_voce_id' => 'required|integer',
|
|
'tabella_millesimale_id' => 'required|integer',
|
|
'descrizione' => 'required|string|max:255',
|
|
'anno_gestione' => 'required|integer|min:2000|max:2100',
|
|
'importo_consuntivo' => 'required|numeric|min:0',
|
|
])->validate();
|
|
|
|
$fatture = $this->getSelectedFatture($state);
|
|
if ($fatture->isEmpty()) {
|
|
Notification::make()->title('Seleziona una fattura XML')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
$legacyVoceId = (int) ($state['legacy_voce_id'] ?? 0);
|
|
$legacy = $this->fetchLegacyVoce($legacyVoceId);
|
|
if (! $legacy) {
|
|
Notification::make()->title('Voce GESCON non trovata')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$tabellaId = (int) ($state['tabella_millesimale_id'] ?? 0);
|
|
|
|
$voceSpesa = $this->firstOrCreateVoceSpesaFromLegacy($legacy, $tabellaId);
|
|
|
|
DB::transaction(function () use ($fatture, $legacy, $tabellaId, $voceSpesa, $state) {
|
|
// PREVENTIVO: usa sempre prev_euro se presente
|
|
if (isset($legacy['preventivo_euro']) && is_numeric($legacy['preventivo_euro']) && (float) $legacy['preventivo_euro'] > 0) {
|
|
$preventivo = Preventivo::query()->firstOrCreate(
|
|
[
|
|
'stabile_id' => $this->stabileAttivo->id,
|
|
'anno_gestione' => (int) ($state['anno_gestione'] ?? now()->format('Y')),
|
|
'tipo_gestione' => 'ordinaria',
|
|
],
|
|
[
|
|
'descrizione' => 'Preventivo ordinario ' . ($state['anno_gestione'] ?? now()->format('Y')),
|
|
'stato' => 'bozza',
|
|
'data_creazione' => now()->toDateString(),
|
|
'versione' => 1,
|
|
],
|
|
);
|
|
|
|
$vp = VocePreventivo::query()->firstOrNew([
|
|
'preventivo_id' => $preventivo->id,
|
|
'voce_spesa_id' => $voceSpesa->id,
|
|
]);
|
|
|
|
$vp->fill([
|
|
'codice' => (string) ($legacy['cod'] ?? $voceSpesa->codice ?? ''),
|
|
'descrizione' => (string) ($legacy['descriz'] ?? $voceSpesa->descrizione),
|
|
'importo_preventivato' => (float) $legacy['preventivo_euro'],
|
|
'tabella_millesimale_id' => $tabellaId,
|
|
'ordinamento' => 0,
|
|
]);
|
|
$vp->save();
|
|
|
|
$preventivo->calcolaImportoTotale();
|
|
}
|
|
|
|
// CONSUNTIVO: registra fattura fornitore + ripartizione
|
|
$totale = (float) ($state['importo_consuntivo'] ?? 0);
|
|
$imponibile = (float) ($state['imponibile'] ?? $fatture->sum('imponibile'));
|
|
$iva = (float) ($state['iva'] ?? $fatture->sum('iva'));
|
|
|
|
$fatturaElettronicaId = null;
|
|
if (($state['tipo_spesa'] ?? 'singola') === 'singola' && ! empty($state['fattura_elettronica_id'])) {
|
|
$fatturaElettronicaId = (int) $state['fattura_elettronica_id'];
|
|
}
|
|
|
|
$fattura = \App\Modules\Contabilita\Models\FatturaFornitore::query()->create([
|
|
'stabile_id' => $this->stabileAttivo->id,
|
|
'fattura_elettronica_id' => $fatturaElettronicaId,
|
|
'fornitore_id' => $state['fornitore_id'] ?? null,
|
|
'data_registrazione' => now()->toDateString(),
|
|
'data_documento' => $state['data_documento'] ?? null,
|
|
'numero_documento' => $state['numero_documento'] ?? null,
|
|
'descrizione' => $state['descrizione'] ?? null,
|
|
'imponibile' => $imponibile,
|
|
'iva' => $iva,
|
|
'totale' => $totale,
|
|
'data_scadenza' => $state['data_scadenza'] ?? null,
|
|
'modalita_pagamento' => $state['modalita_pagamento'] ?? null,
|
|
'netto_da_pagare' => $totale,
|
|
'stato' => 'inserito',
|
|
]);
|
|
|
|
\App\Modules\Contabilita\Models\FatturaFornitoreRiga::query()->create([
|
|
'fattura_id' => $fattura->id,
|
|
'riga' => 1,
|
|
'descrizione' => (string) (($state['descrizione'] ?? '') ?: ($legacy['descriz'] ?? 'Spesa')),
|
|
'imponibile_euro' => $imponibile,
|
|
'iva_euro' => $iva,
|
|
'totale_euro' => $totale,
|
|
'tabella_millesimale_id' => $tabellaId,
|
|
]);
|
|
|
|
app(RipartizioneSpesaService::class)->calcolaRipartizione(
|
|
$voceSpesa,
|
|
$totale,
|
|
$tabellaId,
|
|
[
|
|
'tipo_ripartizione' => 'millesimale',
|
|
'note' => $state['descrizione'] ?? null,
|
|
],
|
|
);
|
|
});
|
|
|
|
Notification::make()->title('Registrazione creata')->success()->send();
|
|
}
|
|
|
|
private function getLegacyVociOptions(): array
|
|
{
|
|
if (! $this->stabileAttivo) {
|
|
return [];
|
|
}
|
|
|
|
try {
|
|
$rows = DB::connection('gescon_import')
|
|
->table('voc_spe')
|
|
->where('cod_stabile', $this->stabileAttivo->codice_stabile)
|
|
->orderBy('descriz')
|
|
->get(['id_vocspe', 'cod', 'descriz', 'tabella']);
|
|
|
|
$out = [];
|
|
foreach ($rows as $r) {
|
|
$out[(int) $r->id_vocspe] = trim((string) $r->cod) . ' — ' . trim((string) $r->descriz) . ' (TAB ' . trim((string) $r->tabella) . ')';
|
|
}
|
|
|
|
return $out;
|
|
} catch (\Throwable $e) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
private function searchLegacyVoci(string $search): array
|
|
{
|
|
if (! $this->stabileAttivo) {
|
|
return [];
|
|
}
|
|
|
|
$search = trim($search);
|
|
if ($search === '') {
|
|
return [];
|
|
}
|
|
|
|
try {
|
|
$rows = DB::connection('gescon_import')
|
|
->table('voc_spe')
|
|
->where('cod_stabile', $this->stabileAttivo->codice_stabile)
|
|
->where(function ($q) use ($search) {
|
|
$like = '%' . str_replace(['%', '_'], ['\\%', '\\_'], $search) . '%';
|
|
$q->where('cod', 'like', $like)
|
|
->orWhere('descriz', 'like', $like)
|
|
->orWhere('tabella', 'like', $like);
|
|
})
|
|
->orderBy('descriz')
|
|
->limit(50)
|
|
->get(['id_vocspe', 'cod', 'descriz', 'tabella']);
|
|
|
|
$out = [];
|
|
foreach ($rows as $r) {
|
|
$out[(int) $r->id_vocspe] = trim((string) $r->cod) . ' — ' . trim((string) $r->descriz) . ' (TAB ' . trim((string) $r->tabella) . ')';
|
|
}
|
|
|
|
return $out;
|
|
} catch (\Throwable $e) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
private function getLegacyVoceLabel($value): ?string
|
|
{
|
|
$id = is_numeric($value) ? (int) $value : null;
|
|
if (! $id || ! $this->stabileAttivo) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
$row = DB::connection('gescon_import')
|
|
->table('voc_spe')
|
|
->where('cod_stabile', $this->stabileAttivo->codice_stabile)
|
|
->where('id_vocspe', $id)
|
|
->first(['cod', 'descriz', 'tabella']);
|
|
|
|
if (! $row) {
|
|
return null;
|
|
}
|
|
|
|
return trim((string) $row->cod) . ' — ' . trim((string) $row->descriz) . ' (TAB ' . trim((string) $row->tabella) . ')';
|
|
} catch (\Throwable $e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private function fetchLegacyVoce(?int $id): ?array
|
|
{
|
|
if (! $this->stabileAttivo || ! $id) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
$row = DB::connection('gescon_import')
|
|
->table('voc_spe')
|
|
->where('cod_stabile', $this->stabileAttivo->codice_stabile)
|
|
->where('id_vocspe', $id)
|
|
->first();
|
|
|
|
if (! $row) {
|
|
return null;
|
|
}
|
|
|
|
return (array) $row;
|
|
} catch (\Throwable $e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private function loadLegacyVoce(int $id): void
|
|
{
|
|
$legacy = $this->fetchLegacyVoce($id);
|
|
if (! $legacy) {
|
|
return;
|
|
}
|
|
|
|
$legacyTabella = isset($legacy['tabella']) ? (string) $legacy['tabella'] : null;
|
|
$mapped = $this->mapLegacyTabellaToTabellaMillesimaleId($legacyTabella);
|
|
|
|
$current = $this->getSchema('form')?->getState() ?? [];
|
|
$descr = (string) ($current['descrizione'] ?? '');
|
|
if ($descr === '') {
|
|
$descr = (string) ($legacy['descriz'] ?? '');
|
|
}
|
|
|
|
$fill = [
|
|
'legacy_tabella' => $legacyTabella,
|
|
'legacy_prev_euro' => isset($legacy['preventivo_euro']) && is_numeric($legacy['preventivo_euro']) ? (float) $legacy['preventivo_euro'] : null,
|
|
'legacy_cons_euro' => isset($legacy['consuntivo_euro']) && is_numeric($legacy['consuntivo_euro']) ? (float) $legacy['consuntivo_euro'] : null,
|
|
'descrizione' => $descr,
|
|
];
|
|
if ($mapped) {
|
|
$fill['tabella_millesimale_id'] = $mapped;
|
|
}
|
|
|
|
$this->getSchema('form')?->fill($fill);
|
|
}
|
|
|
|
private function mapLegacyTabellaToTabellaMillesimaleId(?string $legacyTabella): ?int
|
|
{
|
|
if (! $this->stabileAttivo || ! $legacyTabella) {
|
|
return null;
|
|
}
|
|
|
|
$raw = strtoupper(trim($legacyTabella));
|
|
$candidates = [$raw];
|
|
if (! str_starts_with($raw, 'TAB')) {
|
|
$candidates[] = 'TAB.' . $raw;
|
|
}
|
|
|
|
$q = TabellaMillesimale::query()->where('stabile_id', $this->stabileAttivo->id);
|
|
foreach ($candidates as $c) {
|
|
$found = (clone $q)
|
|
->where(function ($qq) use ($c) {
|
|
$qq->where('codice_tabella', $c)
|
|
->orWhere('nome_tabella', $c);
|
|
})
|
|
->value('id');
|
|
|
|
if ($found) {
|
|
return (int) $found;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function getTabelleOptions(): array
|
|
{
|
|
if (! $this->stabileAttivo) {
|
|
return [];
|
|
}
|
|
|
|
return TabellaMillesimale::query()
|
|
->where('stabile_id', $this->stabileAttivo->id)
|
|
->ordinato()
|
|
->get(['id', 'codice_tabella', 'nome_tabella', 'denominazione'])
|
|
->mapWithKeys(function (TabellaMillesimale $t) {
|
|
$label = $t->codice_tabella ?: ($t->denominazione ?: ($t->nome_tabella ?: null));
|
|
return [$t->id => ($label ?: ('Tabella #' . (int) $t->id))];
|
|
})
|
|
->all();
|
|
}
|
|
|
|
private function getFattureOptions(): array
|
|
{
|
|
if (! $this->stabileAttivo) {
|
|
return [];
|
|
}
|
|
|
|
return FatturaElettronica::query()
|
|
->where('stabile_id', $this->stabileAttivo->id)
|
|
->orderByDesc('data_fattura')
|
|
->limit(200)
|
|
->get()
|
|
->mapWithKeys(function (FatturaElettronica $f) {
|
|
$label = trim(($f->data_fattura?->format('Y-m-d') ?: '') . ' — ' . ($f->fornitore_denominazione ?: 'ND') . ' — ' . ($f->numero_fattura ?: 'ND') . ' — ' . number_format((float) $f->totale, 2, ',', '.') . '€');
|
|
return [$f->id => $label];
|
|
})
|
|
->all();
|
|
}
|
|
|
|
private function getSelectedFatture(array $state)
|
|
{
|
|
if (! $this->stabileAttivo) {
|
|
return collect();
|
|
}
|
|
|
|
if (($state['tipo_spesa'] ?? 'singola') === 'aggregata') {
|
|
$ids = array_values(array_filter(array_map('intval', (array) ($state['fatture_elettroniche_ids'] ?? []))));
|
|
if (count($ids) === 0) {
|
|
return collect();
|
|
}
|
|
|
|
return FatturaElettronica::query()
|
|
->where('stabile_id', $this->stabileAttivo->id)
|
|
->whereIn('id', $ids)
|
|
->get();
|
|
}
|
|
|
|
$id = (int) ($state['fattura_elettronica_id'] ?? 0);
|
|
if (! $id) {
|
|
return collect();
|
|
}
|
|
|
|
return FatturaElettronica::query()
|
|
->where('stabile_id', $this->stabileAttivo->id)
|
|
->where('id', $id)
|
|
->get();
|
|
}
|
|
|
|
private function getParsedOrStoredXmlData(FatturaElettronica $fattura): array
|
|
{
|
|
$data = [
|
|
'pagamento_modalita' => $fattura->pagamento_modalita,
|
|
'pagamento_iban' => $fattura->pagamento_iban,
|
|
'pagamento_bic' => $fattura->pagamento_bic,
|
|
'consumo_valore' => $fattura->consumo_valore,
|
|
'consumo_unita' => $fattura->consumo_unita,
|
|
'consumo_riferimento' => $fattura->consumo_riferimento,
|
|
];
|
|
|
|
$needsParse = empty($data['pagamento_modalita']) && empty($data['pagamento_iban']) && empty($data['consumo_valore']) && empty($data['consumo_riferimento']);
|
|
|
|
if ($needsParse && is_string($fattura->xml_content) && $fattura->xml_content !== '') {
|
|
try {
|
|
return app(FatturaElettronicaXmlParser::class)->parse($fattura->xml_content);
|
|
} catch (\Throwable $e) {
|
|
return $data;
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
private function getFornitoreDenominazione(int $fornitoreId): ?string
|
|
{
|
|
return (string) (\App\Models\Fornitore::query()->whereKey($fornitoreId)->value('ragione_sociale')
|
|
?: \App\Models\Fornitore::query()->whereKey($fornitoreId)->value('nome'));
|
|
}
|
|
|
|
private function firstOrCreateVoceSpesaFromLegacy(array $legacy, int $tabellaId): VoceSpesa
|
|
{
|
|
$descr = trim((string) ($legacy['descriz'] ?? 'Spesa'));
|
|
|
|
$existing = VoceSpesa::query()
|
|
->where('stabile_id', $this->stabileAttivo->id)
|
|
->where('descrizione', $descr)
|
|
->first();
|
|
|
|
if ($existing) {
|
|
if (! $existing->tabella_millesimale_default_id) {
|
|
$existing->tabella_millesimale_default_id = $tabellaId;
|
|
$existing->save();
|
|
}
|
|
return $existing;
|
|
}
|
|
|
|
$categoria = $this->guessCategoria($descr);
|
|
|
|
return VoceSpesa::query()->create([
|
|
'stabile_id' => $this->stabileAttivo->id,
|
|
'descrizione' => $descr,
|
|
'tipo_gestione' => 'ordinaria',
|
|
'categoria' => $categoria,
|
|
'tabella_millesimale_default_id' => $tabellaId,
|
|
'ritenuta_acconto_default' => 0,
|
|
'attiva' => true,
|
|
'ordinamento' => 0,
|
|
]);
|
|
}
|
|
|
|
private function guessCategoria(string $descrizione): string
|
|
{
|
|
$d = mb_strtolower($descrizione);
|
|
if (str_contains($d, 'acqua') || str_contains($d, 'idrico')) {
|
|
return 'acqua';
|
|
}
|
|
if (str_contains($d, 'riscald')) {
|
|
return 'riscaldamento';
|
|
}
|
|
if (str_contains($d, 'energia') || str_contains($d, 'luce') || str_contains($d, 'elettr')) {
|
|
return 'energia';
|
|
}
|
|
return 'generale';
|
|
}
|
|
}
|