163 lines
5.1 KiB
PHP
163 lines
5.1 KiB
PHP
<?php
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\FatturaElettronica;
|
|
use App\Models\Fornitore;
|
|
use App\Models\Stabile;
|
|
use App\Modules\Contabilita\Models\FatturaFornitore;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class GesconFixFattureFornitoriLinkCommand extends Command
|
|
{
|
|
protected $signature = 'gescon:fatture-fix-fornitore-link
|
|
{stabile_id : ID dello stabile}
|
|
{--dry-run : Non scrive, mostra solo cosa aggiornerebbe}
|
|
{--fix-mismatches : Corregge anche i fornitore_id gia valorizzati ma errati}';
|
|
|
|
protected $description = 'Backfill: collega le fatture fornitori contabili al fornitore corretto usando PIVA/CF della Fattura Elettronica.';
|
|
|
|
public function handle(): int
|
|
{
|
|
$stabileId = (int) $this->argument('stabile_id');
|
|
if ($stabileId <= 0) {
|
|
$this->error('stabile_id non valido');
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$dry = (bool) $this->option('dry-run');
|
|
$fixMismatches = (bool) $this->option('fix-mismatches');
|
|
|
|
$stabile = Stabile::query()->select(['id', 'amministratore_id'])->find($stabileId);
|
|
if (! $stabile) {
|
|
$this->error('Stabile non trovato');
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$adminId = (int) ($stabile->amministratore_id ?: 0);
|
|
if ($adminId <= 0) {
|
|
$this->error('Stabile senza amministratore_id');
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$fattureQuery = FatturaFornitore::query()
|
|
->where('stabile_id', $stabileId)
|
|
->whereNotNull('fattura_elettronica_id');
|
|
|
|
if (! $fixMismatches) {
|
|
$fattureQuery->whereNull('fornitore_id');
|
|
}
|
|
|
|
$fatture = $fattureQuery
|
|
->orderBy('id')
|
|
->get(['id', 'fattura_elettronica_id', 'fornitore_id']);
|
|
|
|
$this->info(
|
|
$fixMismatches
|
|
? 'Fatture contabili da verificare: ' . $fatture->count()
|
|
: 'Fatture contabili senza fornitore_id: ' . $fatture->count()
|
|
);
|
|
|
|
$updated = 0;
|
|
$skipped = 0;
|
|
|
|
foreach ($fatture as $fattura) {
|
|
$feId = (int) ($fattura->fattura_elettronica_id ?: 0);
|
|
if ($feId <= 0) {
|
|
$skipped++;
|
|
continue;
|
|
}
|
|
|
|
$fe = FatturaElettronica::query()->find($feId);
|
|
if (! $fe) {
|
|
$skipped++;
|
|
continue;
|
|
}
|
|
|
|
$piva = $this->normalizeId($fe->fornitore_piva);
|
|
$cf = $this->normalizeId($fe->fornitore_cf);
|
|
|
|
$fornitoreId = $this->matchFornitoreIdForAdmin($adminId, $piva, $cf);
|
|
if (! $fornitoreId) {
|
|
$skipped++;
|
|
continue;
|
|
}
|
|
|
|
if ((int) ($fattura->fornitore_id ?: 0) === $fornitoreId) {
|
|
$skipped++;
|
|
continue;
|
|
}
|
|
|
|
$updated++;
|
|
|
|
if ($dry) {
|
|
$this->line("[dry-run] fattura_id={$fattura->id} -> fornitore_id={$fornitoreId}");
|
|
continue;
|
|
}
|
|
|
|
DB::transaction(function () use ($fattura, $fe, $fornitoreId): void {
|
|
$fattura->fornitore_id = $fornitoreId;
|
|
$fattura->save();
|
|
|
|
if ((int) ($fe->fornitore_id ?: 0) !== $fornitoreId) {
|
|
$fe->fornitore_id = $fornitoreId;
|
|
$fe->save();
|
|
}
|
|
});
|
|
}
|
|
|
|
$this->info('✅ Completato' . ($dry ? ' (dry-run)' : ''));
|
|
$this->line(json_encode([
|
|
'stabile_id' => $stabileId,
|
|
'amministratore_id' => $adminId,
|
|
'fix_mismatches' => $fixMismatches,
|
|
'updated' => $updated,
|
|
'skipped' => $skipped,
|
|
], JSON_UNESCAPED_UNICODE));
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function normalizeId(?string $value): string
|
|
{
|
|
$value = strtoupper(trim((string) ($value ?? '')));
|
|
$value = str_replace(' ', '', $value);
|
|
return $value;
|
|
}
|
|
|
|
private function matchFornitoreIdForAdmin(int $adminId, string $pivaNorm, string $cfNorm): ?int
|
|
{
|
|
$base = Fornitore::query()->where('amministratore_id', $adminId);
|
|
|
|
if ($pivaNorm !== '' && $pivaNorm !== 'ND') {
|
|
$match = (clone $base)
|
|
->whereRaw("REPLACE(UPPER(partita_iva), ' ', '') = ?", [$pivaNorm])
|
|
->value('id');
|
|
if ($match) {
|
|
return (int) $match;
|
|
}
|
|
|
|
if (str_starts_with($pivaNorm, 'IT') && strlen($pivaNorm) > 2) {
|
|
$pivaNoIt = substr($pivaNorm, 2);
|
|
$match = (clone $base)
|
|
->whereRaw("REPLACE(UPPER(partita_iva), ' ', '') = ?", [$pivaNoIt])
|
|
->value('id');
|
|
if ($match) {
|
|
return (int) $match;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($cfNorm !== '' && $cfNorm !== 'ND') {
|
|
$match = (clone $base)
|
|
->whereRaw("REPLACE(UPPER(codice_fiscale), ' ', '') = ?", [$cfNorm])
|
|
->value('id');
|
|
if ($match) {
|
|
return (int) $match;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|