netgescon-day0/app/Models/Fornitore.php

297 lines
8.0 KiB
PHP
Executable File

<?php
namespace App\Models;
use App\Support\ArchivioPaths;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class Fornitore extends Model
{
use HasFactory;
protected $table = 'fornitori';
protected $fillable = [
'amministratore_id',
'cod_forn',
'rubrica_id',
'codice_univoco',
'ragione_sociale',
'nome',
'cognome',
'partita_iva',
'codice_fiscale',
'indirizzo',
'civico',
'cap',
'citta',
'provincia',
'nazione',
'email',
'pec',
'iban',
'intestazione_cc_esatta',
'bic',
'modalita_pagamento_predefinita',
'escludi_righe_fe',
'fe_features',
'operational_config',
'telefono',
'telefono_country_code',
'cellulare',
'cellulare_country_code',
'sito_web',
'tags',
'legacy_descrizione',
'note',
'regime_fiscale_id',
'tipologia_cassa_id',
'aliquota_iva_id',
'is_tecnorepair_primary',
'old_id',
];
protected $casts = [
'created_at' => 'datetime',
'updated_at' => 'datetime',
'cod_forn' => 'integer',
'escludi_righe_fe' => 'boolean',
'fe_features' => 'array',
'operational_config' => 'array',
'is_tecnorepair_primary' => 'boolean',
];
/**
* @return array<string, mixed>
*/
public function getFeFeaturesSafeAttribute(): array
{
try {
if (! Schema::hasColumn('fornitori', 'fe_features')) {
return [];
}
} catch (\Throwable) {
return [];
}
return is_array($this->fe_features ?? null) ? $this->fe_features : [];
}
/**
* @return array<string, mixed>
*/
public function getOperationalConfigSafeAttribute(): array
{
try {
if (! Schema::hasColumn('fornitori', 'operational_config')) {
return [];
}
} catch (\Throwable) {
return [];
}
return is_array($this->operational_config ?? null) ? $this->operational_config : [];
}
protected static function booted(): void
{
static::creating(function (Fornitore $fornitore) {
// Allinea sempre il codice univoco al codice della Rubrica (unica sorgente di verità).
if ((empty($fornitore->codice_univoco) || ! is_string($fornitore->codice_univoco)) && (int) ($fornitore->rubrica_id ?? 0) > 0) {
$rubricaCode = RubricaUniversale::query()
->whereKey((int) $fornitore->rubrica_id)
->value('codice_univoco');
if (is_string($rubricaCode) && $rubricaCode !== '') {
$fornitore->codice_univoco = $rubricaCode;
}
}
if (empty($fornitore->codice_univoco) && $fornitore->shouldGenerateCodiceUnivocoLocally()) {
$fornitore->codice_univoco = $fornitore->generateLocalCodiceUnivoco();
}
});
static::created(function (Fornitore $fornitore) {
try {
$fornitore->ensureArchiveStructure();
} catch (\Throwable) {
// ignore
}
});
}
public function ensureArchiveStructure(): void
{
$bases = array_values(array_filter([
ArchivioPaths::fornitoreBase($this),
ArchivioPaths::fornitoreLegacyBase($this),
]));
if ($bases === []) {
return;
}
foreach ($bases as $base) {
foreach ([
'documenti',
'documenti/archivio_per_anno',
'rubrica',
'fe',
'prodotti',
'comunicazioni',
'tecnorepair/imports',
'tecnorepair/allegati',
'temp/upload',
'temp/processing',
'logs',
'google_drive',
] as $folder) {
Storage::disk('local')->makeDirectory($base . '/' . $folder);
}
}
}
protected function shouldGenerateCodiceUnivocoLocally(): bool
{
return $this->getConnection()->getDriverName() !== 'mysql';
}
protected function generateLocalCodiceUnivoco(): string
{
do {
$code = strtoupper(Str::random(8));
} while (self::where('codice_univoco', $code)->exists());
return $code;
}
/**
* Relazione con Amministratore
*/
public function amministratore()
{
return $this->belongsTo(Amministratore::class, 'amministratore_id', 'id');
}
public function rubrica()
{
return $this->belongsTo(RubricaUniversale::class, 'rubrica_id');
}
public function regimeFiscale()
{
return $this->belongsTo(RegimeFiscale::class, 'regime_fiscale_id');
}
public function tipologiaCassa()
{
return $this->belongsTo(TipologiaCassa::class, 'tipologia_cassa_id');
}
public function aliquotaIva()
{
return $this->belongsTo(AliquotaIva::class, 'aliquota_iva_id');
}
/**
* Relazione con Tickets assegnati
*/
public function ticketsAssegnati()
{
return $this->hasMany(Ticket::class, 'assegnato_a_fornitore_id', 'id');
}
public function ticketInterventi()
{
return $this->hasMany(TicketIntervento::class, 'fornitore_id', 'id');
}
public function dipendenti()
{
return $this->hasMany(FornitoreDipendente::class, 'fornitore_id', 'id');
}
public function tecnorepairSchede(): HasMany
{
return $this->hasMany(AssistenzaTecnorepairScheda::class, 'fornitore_id', 'id');
}
public function productSerials(): HasMany
{
return $this->hasMany(ProductSerial::class, 'fornitore_id', 'id');
}
public function products(): HasMany
{
return $this->hasMany(Product::class, 'default_fornitore_id', 'id');
}
public function productOffers(): HasMany
{
return $this->hasMany(ProductOffer::class, 'fornitore_id', 'id');
}
public function getIsTecnoRepairCenterAttribute(): bool
{
if ((bool) ($this->is_tecnorepair_primary ?? false)) {
return true;
}
$label = Str::upper(trim((string) ($this->ragione_sociale ?? '')));
return $label !== '' && Str::contains($label, 'NETHOME');
}
/**
* @return array<string,int>
*/
public function getTecnoRepairStatsAttribute(): array
{
$base = $this->tecnorepairSchede();
return [
'total' => (int) (clone $base)->count(),
'open' => (int) (clone $base)->whereIn('status_bucket', ['open', 'waiting'])->count(),
'closed' => (int) (clone $base)->where('status_bucket', 'closed')->count(),
'serials' => (int) $this->productSerials()->count(),
];
}
/**
* Accessor per l'indirizzo completo
*/
public function getIndirizzoCompletoAttribute()
{
$parts = [];
if ($this->indirizzo) {
$parts[] = $this->indirizzo;
}
if ($this->cap && $this->citta) {
$parts[] = $this->cap . ' ' . $this->citta;
}
if ($this->provincia) {
$parts[] = '(' . $this->provincia . ')';
}
return implode(', ', $parts);
}
/**
* Scope per ricerca
*/
public function scopeSearch($query, $search)
{
return $query->where(function ($q) use ($search) {
$q->where('ragione_sociale', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%")
->orWhere('telefono', 'like', "%{$search}%")
->orWhere('partita_iva', 'like', "%{$search}%");
});
}
}