Aggiornamento dipendenza php-cs-fixer

This commit is contained in:
Pek5892 2024-04-09 12:18:08 +02:00
parent 6c6fb4fd24
commit fedf455b1f
54 changed files with 126 additions and 131 deletions

View File

@ -67,7 +67,7 @@
"willdurand/geocoder": "^4.2"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.10.0",
"friendsofphp/php-cs-fixer": "^3.53",
"rector/rector": "^1.0"
},
"autoload": {

View File

@ -17,8 +17,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
$result['id'] ??= null;
// Form di inserimento riga documento
echo '
<form action="'.base_path().'/editor.php?id_module='.$id_module.'&id_record='.$id_record.'" method="post" id="submit-form">

View File

@ -38,7 +38,7 @@ if (!function_exists('array_column')) {
*/
function array_column($array, $key)
{
return array_map(fn($v) => is_object($v) ? $v->$key : $v[$key], $array);
return array_map(fn ($v) => is_object($v) ? $v->$key : $v[$key], $array);
}
}
@ -53,7 +53,7 @@ if (!function_exists('array_clean')) {
function array_clean($array)
{
if (!empty($array)) {
return array_unique(array_values(array_filter($array, fn($value) => !empty($value))));
return array_unique(array_values(array_filter($array, fn ($value) => !empty($value))));
}
}
}

View File

@ -473,7 +473,7 @@ if ($is_cliente or $is_fornitore or $is_tecnico) {
</div>';
$banche = Banca::where('id_anagrafica', $anagrafica->id)->get();
$banca_predefinita = $banche->first(fn($item) => !empty($item['predefined']));
$banca_predefinita = $banche->first(fn ($item) => !empty($item['predefined']));
$modulo_banche = (new Module())->getByField('name', 'Banche', Models\Locale::getPredefined()->id);
if (!$banche->isEmpty()) {
echo '

View File

@ -192,7 +192,7 @@ class Anagrafica extends Model
*/
public function isTipo($type)
{
return $this->tipi()->get()->search(fn($item, $key) => TipoAnagrafica::find($item->id)->getTranslation('name', \Models\Locale::getPredefined()->id) == $type) !== false;
return $this->tipi()->get()->search(fn ($item, $key) => TipoAnagrafica::find($item->id)->getTranslation('name', \Models\Locale::getPredefined()->id) == $type) !== false;
}
public function delete()

View File

@ -32,19 +32,19 @@ if (!function_exists('aggiorna_sedi_movimenti')) {
$idsede = ($rs[0]['dir'] == 'uscita') ? $rs[0]['idsede_destinazione'] : $rs[0]['idsede_partenza'];
$dbo->query('UPDATE `mg_movimenti` SET `idsede`='.prepare($idsede).' WHERE `reference_type`='.prepare(\Modules\DDT\DDT::class).' AND `reference_id`='.prepare($id));
$dbo->query('UPDATE `mg_movimenti` SET `idsede`='.prepare($idsede).' WHERE `reference_type`='.prepare(Modules\DDT\DDT::class).' AND `reference_id`='.prepare($id));
} elseif ($module == 'documenti') {
$rs = $dbo->fetchArray('SELECT `idsede_partenza`, `idsede_destinazione`, `dir` FROM `co_documenti` INNER JOIN `co_tipidocumento` ON `co_tipidocumento`.`id` = `co_documenti`.`idtipodocumento` WHERE `co_documenti`.`id`='.prepare($id));
$idsede = ($rs[0]['dir'] == 'uscita') ? $rs[0]['idsede_destinazione'] : $rs[0]['idsede_partenza'];
$dbo->query('UPDATE mg_movimenti SET idsede='.prepare($idsede).' WHERE reference_type='.prepare(\Modules\Fatture\Fattura::class).' AND reference_id='.prepare($id));
$dbo->query('UPDATE mg_movimenti SET idsede='.prepare($idsede).' WHERE reference_type='.prepare(Modules\Fatture\Fattura::class).' AND reference_id='.prepare($id));
} elseif ($module == 'interventi') {
$rs = $dbo->fetchArray('SELECT idsede_partenza, idsede_destinazione FROM in_interventi WHERE in_interventi.id='.prepare($id));
$idsede = $rs[0]['idsede_partenza'];
$dbo->query('UPDATE mg_movimenti SET idsede='.prepare($idsede).' WHERE reference_type='.prepare(\Modules\Interventi\Intervento::class).' AND reference_id='.prepare($id));
$dbo->query('UPDATE mg_movimenti SET idsede='.prepare($idsede).' WHERE reference_type='.prepare(Modules\Interventi\Intervento::class).' AND reference_id='.prepare($id));
}
}
}

View File

@ -296,7 +296,7 @@ class Articolo extends Model
}
$movimenti = $movimenti->get()
->mapToGroups(fn($item, $key) => [$item->idsede => (float) $item->attributes['qta']])
->mapToGroups(fn ($item, $key) => [$item->idsede => (float) $item->attributes['qta']])
->toArray();
return $movimenti;

View File

@ -73,7 +73,7 @@ class Combinazione extends Model
$result = parent::save($options);
// Sincronizzazione dei campi condivisi con la Combinazione
$sincro = collect($this->toArray())->filter(fn($value, $key) => in_array($key, self::$campi_combinazione));
$sincro = collect($this->toArray())->filter(fn ($value, $key) => in_array($key, self::$campi_combinazione));
$this->sincronizzaCampi($sincro->toArray());
return $result;
@ -176,7 +176,7 @@ class Combinazione extends Model
return;
}
$sincro = collect($articolo->toArray())->filter(fn($value, $key) => in_array($key, self::$campi_varianti));
$sincro = collect($articolo->toArray())->filter(fn ($value, $key) => in_array($key, self::$campi_varianti));
$combinazione->sincronizzaCampi($sincro->toArray());
}
@ -215,7 +215,7 @@ class Combinazione extends Model
->update($values);
// Filtro campi combinazioni
$combo = collect($values)->filter(fn($value, $key) => in_array($key, self::$campi_combinazione));
$combo = collect($values)->filter(fn ($value, $key) => in_array($key, self::$campi_combinazione));
// Aggiornamento dati combinazioni
database()->table('mg_combinazioni')

View File

@ -77,9 +77,9 @@ switch (post('op')) {
// Ricerca fattura per anagrafica tra le registrate
$id_sede = $raggruppamento == 'sede' ? $documento_import->idsede : 0;
if ($raggruppamento == 'sede') {
$fattura = $documenti->first(fn($item, $key) => $item->anagrafica->id == $id_anagrafica && $item->idsede_destinazione == $id_sede);
$fattura = $documenti->first(fn ($item, $key) => $item->anagrafica->id == $id_anagrafica && $item->idsede_destinazione == $id_sede);
} else {
$fattura = $documenti->first(fn($item, $key) => $item->anagrafica->id == $id_anagrafica);
$fattura = $documenti->first(fn ($item, $key) => $item->anagrafica->id == $id_anagrafica);
}
// Ricerca fattura per anagrafica se l'impostazione di accodamento è selezionata

View File

@ -77,9 +77,9 @@ switch (post('op')) {
// Ricerca fattura per anagrafica tra le registrate
$id_sede = $raggruppamento == 'sede' ? $documento_import->idsede_destinazione : 0;
if ($raggruppamento == 'sede') {
$fattura = $documenti->first(fn($item, $key) => $item->anagrafica->id == $id_anagrafica && $item->idsede_destinazione == $id_sede);
$fattura = $documenti->first(fn ($item, $key) => $item->anagrafica->id == $id_anagrafica && $item->idsede_destinazione == $id_sede);
} else {
$fattura = $documenti->first(fn($item, $key) => $item->anagrafica->id == $id_anagrafica);
$fattura = $documenti->first(fn ($item, $key) => $item->anagrafica->id == $id_anagrafica);
}
// Ricerca fattura per anagrafica se l'impostazione di accodamento è selezionata

View File

@ -264,7 +264,7 @@ if (!function_exists('verifica_numero_ddt')) {
do {
$numero = Generator::generate($maschera, $ultimo, 1, Generator::dateToPattern($data));
$filtered = $documenti->reject(fn($item, $key) => $item->numero_esterno == $numero);
$filtered = $documenti->reject(fn ($item, $key) => $item->numero_esterno == $numero);
if ($documenti->count() == $filtered->count()) {
return $numero;

View File

@ -153,7 +153,7 @@ class DDT extends Document
{
$righe = $this->getRighe();
$peso_lordo = $righe->sum(fn($item) => $item->isArticolo() ? $item->articolo->peso_lordo * $item->qta : 0);
$peso_lordo = $righe->sum(fn ($item) => $item->isArticolo() ? $item->articolo->peso_lordo * $item->qta : 0);
return $peso_lordo;
}
@ -167,7 +167,7 @@ class DDT extends Document
{
$righe = $this->getRighe();
$volume = $righe->sum(fn($item) => $item->isArticolo() ? $item->articolo->volume * $item->qta : 0);
$volume = $righe->sum(fn ($item) => $item->isArticolo() ? $item->articolo->volume * $item->qta : 0);
return $volume;
}

View File

@ -48,7 +48,6 @@ if ($fattura) {
$stato_fe = $dbo->fetchOne('SELECT codice_stato_fe FROM co_documenti WHERE id = '.$fattura->id);
}
$ops = ['update', 'add_intervento', 'manage_documento_fe', 'manage_riga_fe', 'manage_articolo', 'manage_sconto', 'manage_riga', 'manage_descrizione', 'unlink_intervento', 'delete_riga', 'copy_riga', 'add_serial', 'add_articolo', 'edit-price'];
if ($dir === 'entrata' && in_array($stato_fe['codice_stato_fe'], ['WAIT', 'RC', 'MC', 'QUEUE', 'DT', 'EC01', 'NE']) && Interaction::isEnabled() && in_array($op, $ops)) {

View File

@ -81,7 +81,7 @@ if (isset($id_record)) {
$fattura_acquisto_originale = null;
if (!empty($fattura)) {
$reverse_charge = $fattura->getRighe()->first(fn($item, $key) => $item->aliquota != null && substr($item->aliquota->codice_natura_fe, 0, 2) == 'N6')->id;
$reverse_charge = $fattura->getRighe()->first(fn ($item, $key) => $item->aliquota != null && substr($item->aliquota->codice_natura_fe, 0, 2) == 'N6')->id;
$autofattura_vendita = Fattura::find($fattura->id_autofattura);
$abilita_autofattura = (($fattura->anagrafica->nazione->iso2 != 'IT' && !empty($fattura->anagrafica->nazione->iso2)) || $reverse_charge) && $dir == 'uscita' && $fattura->id_autofattura == null;

View File

@ -449,7 +449,7 @@ if (!function_exists('verifica_numero_fattura')) {
do {
$numero = Generator::generate($maschera, $ultimo, 1, Generator::dateToPattern($data));
$filtered = $documenti->reject(fn($item, $key) => $item->numero_esterno == $numero);
$filtered = $documenti->reject(fn ($item, $key) => $item->numero_esterno == $numero);
if ($documenti->count() == $filtered->count()) {
return $numero;
@ -469,7 +469,7 @@ if (!function_exists('verifica_numero_fattura')) {
$righe = [];
// Righe documento
$righe_documento = $documento->getRighe()->where('idintervento', '!=', null)->groupBy(fn($item, $key) => $item['prezzo_unitario'].'|'.$item['idiva'].'|'.$item['sconto_unitario']);
$righe_documento = $documento->getRighe()->where('idintervento', '!=', null)->groupBy(fn ($item, $key) => $item['prezzo_unitario'].'|'.$item['idiva'].'|'.$item['sconto_unitario']);
if (setting('Raggruppa attività per tipologia in fattura') && !$righe_documento->isEmpty()) {
$articoli = [];

View File

@ -281,7 +281,7 @@ class Fattura extends Document
{
$righe = $this->getRighe();
$peso_lordo = $righe->sum(fn($item) => $item->isArticolo() ? $item->articolo->peso_lordo * $item->qta : 0);
$peso_lordo = $righe->sum(fn ($item) => $item->isArticolo() ? $item->articolo->peso_lordo * $item->qta : 0);
return $peso_lordo;
}
@ -295,7 +295,7 @@ class Fattura extends Document
{
$righe = $this->getRighe();
$volume = $righe->sum(fn($item) => $item->isArticolo() ? $item->articolo->volume * $item->qta : 0);
$volume = $righe->sum(fn ($item) => $item->isArticolo() ? $item->articolo->volume * $item->qta : 0);
return $volume;
}
@ -496,7 +496,7 @@ class Fattura extends Document
{
$nome = 'Ricevuta';
return $this->uploads()->filter(fn($item) => false !== strstr($item->getTranslation('name'), $nome))->sortBy('created_at');
return $this->uploads()->filter(fn ($item) => false !== strstr($item->getTranslation('name'), $nome))->sortBy('created_at');
}
/**

View File

@ -47,7 +47,7 @@ class Bollo
return $this->fattura->bollo;
}
$righe_bollo = $this->fattura->getRighe()->filter(fn($item, $key) => $item->aliquota != null && in_array($item->aliquota->codice_natura_fe, ['N2.1', 'N2.2', 'N3.5', 'N3.6', 'N4']));
$righe_bollo = $this->fattura->getRighe()->filter(fn ($item, $key) => $item->aliquota != null && in_array($item->aliquota->codice_natura_fe, ['N2.1', 'N2.2', 'N3.5', 'N3.6', 'N4']));
$importo_righe_bollo = $righe_bollo->sum('subtotale');
// Leggo la marca da bollo se c'è e se il netto a pagare supera la soglia
@ -70,7 +70,7 @@ class Bollo
public function manageRigaMarcaDaBollo()
{
$riga = $this->fattura->rigaBollo;
$righe_bollo = $this->fattura->getRighe()->filter(fn($item, $key) => $item->aliquota != null && in_array($item->aliquota->codice_natura_fe, ['N2.1', 'N2.2', 'N3.5', 'N3.6', 'N4']))->first();
$righe_bollo = $this->fattura->getRighe()->filter(fn ($item, $key) => $item->aliquota != null && in_array($item->aliquota->codice_natura_fe, ['N2.1', 'N2.2', 'N3.5', 'N3.6', 'N4']))->first();
$addebita_bollo = $this->fattura->addebita_bollo;
$marca_da_bollo = $this->getBollo();
@ -79,7 +79,7 @@ class Bollo
if (setting('Cassa previdenziale predefinita')) {
$cassa_pred = database()->fetchOne('SELECT percentuale FROM co_rivalse WHERE id='.setting('Cassa previdenziale predefinita'));
}
// Verifico se la fattura ha righe con rivalsa applicata, esclusa la marca da bollo
$rivalsa = ($this->fattura->rivalsainps > 0 && $this->fattura->rivalsainps != (setting('Importo marca da bollo') * $cassa_pred['percentuale'] / 100)) ? 1 : 0;

View File

@ -626,11 +626,11 @@ switch (post('op')) {
$intervento->idreferente = $documento->idreferente;
$intervento->idagente = $documento->idagente;
if ($class == \Modules\Preventivi\Preventivo::class) {
if ($class == Modules\Preventivi\Preventivo::class) {
$intervento->id_preventivo = $documento->id;
$intervento->richiesta = 'Attività creata da preventivo num. '.$documento->numero.'<br>'.$documento->nome;
}
if ($class == \Modules\Ordini\Ordine::class) {
if ($class == Modules\Ordini\Ordine::class) {
$intervento->id_ordine = $documento->id;
$intervento->richiesta = 'Attività creata da ordine num. '.$documento->numero_esterno;
}

View File

@ -190,7 +190,7 @@ if (!function_exists('aggiungi_intervento_in_fattura')) {
} else {
$decimals = setting('Cifre decimali per quantità');
$ore_di_lavoro = $sessioni->groupBy(fn($item, $key) => $item['prezzo_orario'].'|'.$item['sconto_unitario'].'|'.$item['tipo_sconto']);
$ore_di_lavoro = $sessioni->groupBy(fn ($item, $key) => $item['prezzo_orario'].'|'.$item['sconto_unitario'].'|'.$item['tipo_sconto']);
foreach ($ore_di_lavoro as $gruppo) {
$sessione = $gruppo->first();
$riga = Riga::build($fattura);
@ -232,7 +232,7 @@ if (!function_exists('aggiungi_intervento_in_fattura')) {
}
// Diritti di chiamata raggruppati per costo
$diritti_chiamata = $sessioni->where('prezzo_diritto_chiamata', '>', 0)->groupBy(fn($item, $key) => $item['prezzo_diritto_chiamata']);
$diritti_chiamata = $sessioni->where('prezzo_diritto_chiamata', '>', 0)->groupBy(fn ($item, $key) => $item['prezzo_diritto_chiamata']);
foreach ($diritti_chiamata as $gruppo) {
$diritto_chiamata = $gruppo->first();
$riga = Riga::build($fattura);
@ -263,7 +263,7 @@ if (!function_exists('aggiungi_intervento_in_fattura')) {
}
// Viaggi raggruppati per costo
$viaggi = $sessioni->where('prezzo_km_unitario', '>', 0)->groupBy(fn($item, $key) => $item['prezzo_km_unitario'].'|'.$item['scontokm_unitario'].'|'.$item['tipo_scontokm']);
$viaggi = $sessioni->where('prezzo_km_unitario', '>', 0)->groupBy(fn ($item, $key) => $item['prezzo_km_unitario'].'|'.$item['scontokm_unitario'].'|'.$item['tipo_scontokm']);
foreach ($viaggi as $gruppo) {
$qta_trasferta = $gruppo->sum('km');
if ($qta_trasferta == 0) {
@ -365,7 +365,7 @@ if (!function_exists('verifica_numero_intervento')) {
do {
$numero = Generator::generate($maschera, $ultimo, 1, Generator::dateToPattern($data), $data);
$filtered = $documenti->reject(fn($item, $key) => $item->codice == $numero);
$filtered = $documenti->reject(fn ($item, $key) => $item->codice == $numero);
if ($documenti->count() == $filtered->count()) {
return $numero;

View File

@ -24,7 +24,7 @@ include_once __DIR__.'/../../../core.php';
// Interventi da pianificare NON completati
$interventi_da_pianificare = Intervento::doesntHave('sessioni')
->orderByRaw('IF(data_scadenza IS NULL, data_richiesta, data_scadenza)')
->whereHas('stato', fn($query) => $query->where('is_completato', '=', 0))
->whereHas('stato', fn ($query) => $query->where('is_completato', '=', 0))
->get();
$raggruppamenti = $interventi_da_pianificare->groupBy(function ($item, $key) {
$data = $item->data_scadenza ?: $item->data_richiesta;

View File

@ -72,9 +72,9 @@ switch (post('op')) {
// Ricerca fattura per anagrafica tra le registrate
$id_sede = $raggruppamento == 'sede' ? $documento_import->idsede : 0;
if ($raggruppamento == 'sede') {
$fattura = $documenti->first(fn($item, $key) => $item->anagrafica->id == $id_anagrafica && $item->idsede_destinazione == $id_sede);
$fattura = $documenti->first(fn ($item, $key) => $item->anagrafica->id == $id_anagrafica && $item->idsede_destinazione == $id_sede);
} else {
$fattura = $documenti->first(fn($item, $key) => $item->anagrafica->id == $id_anagrafica);
$fattura = $documenti->first(fn ($item, $key) => $item->anagrafica->id == $id_anagrafica);
}
// Ricerca fattura per anagrafica se l'impostazione di accodamento è selezionata

View File

@ -19,10 +19,8 @@
namespace Modules\Pagamenti;
use Carbon\Carbon;
use Common\SimpleModelTrait;
use Illuminate\Database\Eloquent\Model;
use Modules\Fatture\Fattura;
use Traits\RecordTrait;
class PagamentoLang extends Model

View File

@ -46,7 +46,7 @@ switch (filter('op')) {
case 'add':
$descrizione = filter('descrizione');
if (empty($dbo->fetchArray('SELECT `dt_porto`.`id` FROM `dt_porto` LEFT JOIN `dt_porto_lang` ON (`dt_porto_lang`.`id_record` = `dt_porto`.`id` AND `dt_porto_lang`.`id_lang` = '.Models\Locale::getDefault()->id.') WHERE `name`='.prepare($descrizione)))) {
if (empty($dbo->fetchArray('SELECT `dt_porto`.`id` FROM `dt_porto` LEFT JOIN `dt_porto_lang` ON (`dt_porto_lang`.`id_record` = `dt_porto`.`id` AND `dt_porto_lang`.`id_lang` = '.Models\Locale::getDefault()->id.') WHERE `name`='.prepare($descrizione)))) {
$dbo->insert('dt_porto', [
'created_at' => 'NOW()',
]);

View File

@ -73,9 +73,9 @@ switch (post('op')) {
// Ricerca fattura per anagrafica tra le registrate
$id_sede = $raggruppamento == 'sede' ? $documento_import->idsede : 0;
if ($raggruppamento == 'sede') {
$fattura = $documenti->first(fn($item, $key) => $item->anagrafica->id == $id_anagrafica && $item->idsede_destinazione == $id_sede);
$fattura = $documenti->first(fn ($item, $key) => $item->anagrafica->id == $id_anagrafica && $item->idsede_destinazione == $id_sede);
} else {
$fattura = $documenti->first(fn($item, $key) => $item->anagrafica->id == $id_anagrafica);
$fattura = $documenti->first(fn ($item, $key) => $item->anagrafica->id == $id_anagrafica);
}
// Ricerca fattura per anagrafica se l'impostazione di accodamento è selezionata

View File

@ -20,6 +20,7 @@
include_once __DIR__.'/../../core.php';
use PHPSQLParser\PHPSQLParser;
if (isset($id_record)) {
$record = $dbo->fetchOne('SELECT
`zz_segments`.*,
@ -39,10 +40,9 @@ if (isset($id_record)) {
$table = $parsed['FROM'][0]['table'];
if ($record['is_sezionale'] == 1) {
$righe = $dbo->fetchArray('SELECT COUNT(*) AS tot FROM ' . $table . ' WHERE `id_segment` = ' . prepare($id_record));
$righe = $dbo->fetchArray('SELECT COUNT(*) AS tot FROM '.$table.' WHERE `id_segment` = '.prepare($id_record));
$tot = $righe[0]['tot'];
} else {
$tot = 0;
}
}
}

View File

@ -267,7 +267,7 @@ echo '
</div>';
// Articoli più venduti
$articoli = $dbo->fetchArray("SELECT
$articoli = $dbo->fetchArray('SELECT
SUM(IF(`reversed`=1, -`co_righe_documenti`.`qta`, `co_righe_documenti`.`qta`)) AS qta,
SUM(IF(`reversed`=1, -(`co_righe_documenti`.`subtotale` - `co_righe_documenti`.`sconto`), (`co_righe_documenti`.`subtotale` - `co_righe_documenti`.`sconto`))) AS totale,
`mg_articoli`.`id`,
@ -277,29 +277,29 @@ $articoli = $dbo->fetchArray("SELECT
FROM
`co_documenti`
INNER JOIN `co_statidocumento` ON `co_statidocumento`.`id` = `co_documenti`.`idstatodocumento`
LEFT JOIN `co_statidocumento_lang` ON `co_statidocumento_lang`.`id_record` = `co_statidocumento`.`id` AND `co_statidocumento_lang`.`id_lang` = ".prepare(Models\Locale::getDefault()->id)."
LEFT JOIN `co_statidocumento_lang` ON `co_statidocumento_lang`.`id_record` = `co_statidocumento`.`id` AND `co_statidocumento_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).'
INNER JOIN `co_tipidocumento` ON `co_documenti`.`idtipodocumento`=`co_tipidocumento`.`id`
INNER JOIN `co_righe_documenti` ON `co_righe_documenti`.`iddocumento`=`co_documenti`.`id`
INNER JOIN `mg_articoli` ON `mg_articoli`.`id`=`co_righe_documenti`.`idarticolo`
LEFT JOIN `mg_articoli_lang` ON (`mg_articoli_lang`.`id_record`=`mg_articoli`.`id` AND `mg_articoli_lang`.`id_lang` = ".prepare(Models\Locale::getDefault()->id).")
LEFT JOIN `mg_articoli_lang` ON (`mg_articoli_lang`.`id_record`=`mg_articoli`.`id` AND `mg_articoli_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id).")
INNER JOIN `zz_segments` ON `co_documenti`.`id_segment`=`zz_segments`.`id`
WHERE
`co_tipidocumento`.`dir`='entrata'
AND `co_statidocumento_lang`.`name` IN ('Pagato', 'Parzialmente pagato', 'Emessa')
AND `co_documenti`.`data` BETWEEN ".prepare($start)." AND ".prepare($end)."
AND `co_documenti`.`data` BETWEEN ".prepare($start).' AND '.prepare($end).'
AND `zz_segments`.`autofatture`=0
GROUP BY
`co_righe_documenti`.`idarticolo`
ORDER BY
`qta` DESC LIMIT 20");
`qta` DESC LIMIT 20');
$totale = $dbo->fetchArray("SELECT
$totale = $dbo->fetchArray('SELECT
SUM(IF(`reversed`=1, - `co_righe_documenti`.`qta`, `co_righe_documenti`.`qta`)) AS totale_qta,
SUM(IF(`reversed`=1, - (`co_righe_documenti`.`subtotale` - `co_righe_documenti`.`sconto`), (`co_righe_documenti`.`subtotale` - `co_righe_documenti`.`sconto`))) AS totale
FROM
`co_documenti`
INNER JOIN `co_statidocumento` ON `co_statidocumento`.`id` = `co_documenti`.`idstatodocumento`
LEFT JOIN `co_statidocumento_lang` ON `co_statidocumento_lang`.`id_record` = `co_statidocumento`.`id` AND `co_statidocumento_lang`.`id_lang` = ".prepare(Models\Locale::getDefault()->id)."
LEFT JOIN `co_statidocumento_lang` ON `co_statidocumento_lang`.`id_record` = `co_statidocumento`.`id` AND `co_statidocumento_lang`.`id_lang` = '.prepare(Models\Locale::getDefault()->id)."
INNER JOIN `co_tipidocumento` ON `co_documenti`.`idtipodocumento`=`co_tipidocumento`.`id`
INNER JOIN `co_righe_documenti` ON `co_righe_documenti`.`iddocumento`=`co_documenti`.`id`
INNER JOIN `mg_articoli` ON `mg_articoli`.`id`=`co_righe_documenti`.`idarticolo`
@ -307,8 +307,8 @@ $totale = $dbo->fetchArray("SELECT
WHERE
`co_tipidocumento`.`dir`='entrata'
AND `co_statidocumento_lang`.name IN ('Pagato', 'Parzialmente pagato', 'Emessa')
AND `co_documenti`.`data` BETWEEN ".prepare($start)." AND ".prepare($end)."
AND `zz_segments`.`autofatture`=0");
AND `co_documenti`.`data` BETWEEN ".prepare($start).' AND '.prepare($end).'
AND `zz_segments`.`autofatture`=0');
echo '
<div class="col-md-6">

View File

@ -278,7 +278,7 @@ function renderElencoModuli($elenco, $depth = 0)
->where('zz_plugins_lang.id_lang', '=', Models\Locale::getDefault()->id);
})
->where('idmodule_to', '=', $record['id'])
->get()->map(fn($i) => (array) $i)->toArray();
->get()->map(fn ($i) => (array) $i)->toArray();
$elenco_plugin = renderElencoModuli($plugins, $depth + 1);
}

View File

@ -78,7 +78,7 @@ switch (filter('op')) {
// Aggiornamento traduzione nome campo
$vista = View::find($id);
$vista->setTranslation('name', $name);
// Aggiornamento dei permessi relativi
$dbo->sync('zz_group_view', ['id_vista' => $id], ['id_gruppo' => (array) post('gruppi')[$c]]);
} else {
@ -156,7 +156,7 @@ switch (filter('op')) {
case 'test':
$module_query = Util\Query::getQuery(Module::find(get('id_record')));
try{
try {
$dbo->fetchArray($module_query.' LIMIT 1');
echo 'ok';
} catch (PDOException $e) {

View File

@ -39,7 +39,7 @@ foreach ($fields as $key => $field) {
<div class="box collapsed-box box-'.($field->visible ? 'success' : 'danger').'">
<div class="box-header with-border">
<h3 class="box-title">'.
$field->getTranslation('name').' <small class="text-muted tip" title="'.(new \Carbon\Carbon($field->updated_at))->format('d/m/Y H:i').'">'.(new \Carbon\Carbon($field->updated_at))->diffForHumans().'</small>
$field->getTranslation('name').' <small class="text-muted tip" title="'.(new Carbon\Carbon($field->updated_at))->format('d/m/Y H:i').'">'.(new Carbon\Carbon($field->updated_at))->diffForHumans().'</small>
</h3>
<div class="box-tools pull-right">
@ -60,14 +60,14 @@ foreach ($fields as $key => $field) {
<div class="row">
<div class="col-md-12">
'.input([
'type' => 'textarea',
'label' => tr('Query prevista'),
'name' => 'query['.$key.']',
'required' => 1,
'readonly' => ''.(!$editable).'',
'value' => $field->query,
'help' => tr('Nome effettivo del campo sulla tabella oppure subquery che permette di ottenere il valore del campo.').'<br>'.tr('ATTENZIONE: utilizza sempre i caratteri < o > seguiti da spazio!'),
]).'
'type' => 'textarea',
'label' => tr('Query prevista'),
'name' => 'query['.$key.']',
'required' => 1,
'readonly' => ''.(!$editable).'',
'value' => $field->query,
'help' => tr('Nome effettivo del campo sulla tabella oppure subquery che permette di ottenere il valore del campo.').'<br>'.tr('ATTENZIONE: utilizza sempre i caratteri < o > seguiti da spazio!'),
]).'
</div>
</div>
@ -120,13 +120,13 @@ foreach ($fields as $key => $field) {
</div>
</div>';
if ($editable) {
echo '
if ($editable) {
echo '
<a class="btn btn-danger ask pull-right" data-backto="record-edit" data-id="'.$field->id.'">
<i class="fa fa-trash"></i> '.tr('Elimina').'
</a>';
}
echo '
}
echo '
</div>
</div>';
}

View File

@ -1387,7 +1387,7 @@ class FatturaElettronica
$result = [];
// Righe del documento
$iva_descrizioni = $righe->first(fn($item, $key) => $item->aliquota != null)->aliquota;
$iva_descrizioni = $righe->first(fn ($item, $key) => $item->aliquota != null)->aliquota;
$order = 1;
foreach ($righe as $idx => $riga) {
@ -1556,7 +1556,7 @@ class FatturaElettronica
}
// Riepiloghi per IVA per percentuale
$riepiloghi_percentuale = $righe->filter(fn($item, $key) => $item->aliquota != null && $item->aliquota->codice_natura_fe == null)->groupBy(fn($item, $key) => $item->aliquota->percentuale);
$riepiloghi_percentuale = $righe->filter(fn ($item, $key) => $item->aliquota != null && $item->aliquota->codice_natura_fe == null)->groupBy(fn ($item, $key) => $item->aliquota->percentuale);
foreach ($riepiloghi_percentuale as $riepilogo) {
$totale = round($riepilogo->sum('totale_imponibile') + $riepilogo->sum('rivalsa_inps'), 2);
$imposta = round($riepilogo->sum('iva') + $riepilogo->sum('iva_rivalsa_inps'), 2);
@ -1588,7 +1588,7 @@ class FatturaElettronica
}
// Riepiloghi per IVA per natura
$riepiloghi_natura = $righe->filter(fn($item, $key) => $item->aliquota != null && $item->aliquota->codice_natura_fe != null)->groupBy(fn($item, $key) => $item->aliquota->codice_natura_fe);
$riepiloghi_natura = $righe->filter(fn ($item, $key) => $item->aliquota != null && $item->aliquota->codice_natura_fe != null)->groupBy(fn ($item, $key) => $item->aliquota->codice_natura_fe);
foreach ($riepiloghi_natura as $riepilogo) {
$totale = round($riepilogo->sum('totale_imponibile') + $riepilogo->sum('rivalsa_inps'), 2);
$imposta = round($riepilogo->sum('iva') + $riepilogo->sum('iva_rivalsa_inps'), 2);

View File

@ -254,20 +254,20 @@ switch (filter('op')) {
}
// Ricerca del tipo di documento più utilizzato
$tipi = $fatture->groupBy(fn($item, $key) => $item->tipo->id)->transform(fn($item, $key) => $item->count());
$tipi = $fatture->groupBy(fn ($item, $key) => $item->tipo->id)->transform(fn ($item, $key) => $item->count());
$id_tipo = $tipi->sort()->keys()->last();
// Ricerca del conto più utilizzato
$conti = $righe->groupBy(fn($item, $key) => $item->idconto)->transform(fn($item, $key) => $item->count());
$conti = $righe->groupBy(fn ($item, $key) => $item->idconto)->transform(fn ($item, $key) => $item->count());
$id_conto = $conti->sort()->keys()->last();
$conto = $database->fetchOne('SELECT * FROM co_pianodeiconti3 WHERE id = '.prepare($id_conto));
// Ricerca dell'IVA più utilizzata secondo percentuali
$iva = [];
$percentuali_iva = $righe->groupBy(fn($item, $key) => $item->aliquota->percentuale);
$percentuali_iva = $righe->groupBy(fn ($item, $key) => $item->aliquota->percentuale);
foreach ($percentuali_iva as $key => $values) {
$aliquote = $values->mapToGroups(fn($item, $key) => [$item->aliquota->id => $item->aliquota]);
$id_aliquota = $aliquote->map(fn($item, $key) => $item->count())->sort()->keys()->last();
$aliquote = $values->mapToGroups(fn ($item, $key) => [$item->aliquota->id => $item->aliquota]);
$id_aliquota = $aliquote->map(fn ($item, $key) => $item->count())->sort()->keys()->last();
$aliquota = $aliquote[$id_aliquota]->first();
$iva[$key] = [

View File

@ -87,7 +87,7 @@ class FatturaElettronica
$plugins = $module->plugins;
if (!empty($plugins)) {
$plugin = $plugins->first(fn($value, $key) => $value->getTranslation('name') == 'Fatturazione Elettronica');
$plugin = $plugins->first(fn ($value, $key) => $value->getTranslation('name') == 'Fatturazione Elettronica');
self::$directory = base_dir().'/'.$plugin->upload_directory;
}

View File

@ -50,7 +50,7 @@ class InvoiceHook extends CachedManager
if (!empty($plugins)) {
$notify = !empty($count);
$plugin = $plugins->first(fn($value, $key) => $value->getTranslation('name') == 'Fatturazione Elettronica');
$plugin = $plugins->first(fn ($value, $key) => $value->getTranslation('name') == 'Fatturazione Elettronica');
$link = base_path().'/controller.php?id_module='.$module->id.'#tab_'.$plugin->id;
}

View File

@ -50,7 +50,7 @@ echo '
<h4>'.tr('Elenco fornitori').'</h4>';
$dettagli_fornitori = DettaglioFornitore::where('id_articolo', $id_record)->get()
->mapToGroups(fn($item, $key) => [$item->id_fornitore => $item]);
->mapToGroups(fn ($item, $key) => [$item->id_fornitore => $item]);
$prezzi_fornitori = DettaglioPrezzo::where('id_articolo', $id_articolo)
->where('dir', 'uscita')
->get()

View File

@ -81,7 +81,7 @@ switch ($action) {
->whereYear('co_fatturazione_contratti.data_scadenza', $year)
->get();
$raggruppamenti = $pianificazioni->groupBy(fn($item) => ucfirst($item->data_scadenza->format('m')));
$raggruppamenti = $pianificazioni->groupBy(fn ($item) => ucfirst($item->data_scadenza->format('m')));
$ret = [];
foreach ($raggruppamenti as $i => $item) {

View File

@ -86,7 +86,7 @@ class Pianificazione extends Document
$p = $this;
return $pianificazioni->search(fn($item) => $item->id == $p->id) + 1;
return $pianificazioni->search(fn ($item) => $item->id == $p->id) + 1;
}
public function getRighe()
@ -96,11 +96,11 @@ class Pianificazione extends Document
$numero_righe = $righe->count() / $pianificazioni->count();
$p = $this;
$index = $pianificazioni->search(fn($item) => $item->id == $p->id);
$index = $pianificazioni->search(fn ($item) => $item->id == $p->id);
$skip = $pianificazioni->count();
return $righe->filter(fn($value, $key) => $key % $skip == $index);
return $righe->filter(fn ($value, $key) => $key % $skip == $index);
}
public function articoli()

View File

@ -102,7 +102,7 @@ switch ($operazione) {
$promemoria_contratto = $contratto->promemoria()
->where('idtipointervento', $promemoria_originale->tipo->id)
->get()
->groupBy(fn($item) => $item->data_richiesta->toDateString());
->groupBy(fn ($item) => $item->data_richiesta->toDateString());
$date_preimpostate = $promemoria_contratto->keys()->toArray();

View File

@ -38,7 +38,7 @@ if ($elenco_promemoria->isEmpty()) {
return;
}
$raggruppamenti = $elenco_promemoria->groupBy(fn($item) => $item->data_richiesta->format('Y-m'));
$raggruppamenti = $elenco_promemoria->groupBy(fn ($item) => $item->data_richiesta->format('Y-m'));
$counter = 0;
foreach ($raggruppamenti as $mese => $raggruppamento) {

View File

@ -43,7 +43,7 @@ switch (filter('op')) {
$descrizione = 'Fattura num. '.$documento->numero_esterno ?: $documento->numero;
// Individuazione altre scadenze del documento
$scadenze_documento = $documento->scadenze->sortBy('scadenza');
$pos = $scadenze_documento->search(fn($item, $key) => $item->id == $scadenza->id);
$pos = $scadenze_documento->search(fn ($item, $key) => $item->id == $scadenza->id);
// Generazione della descrizione del pagamento
$descrizione .= tr(' pag _NUM_/_TOT_', [

View File

@ -93,13 +93,13 @@ $totale_ddt_uscita = $ddt_uscita->sum('totale_imponibile');
$segmenti = $dbo->select('zz_segments', 'id', [], ['autofatture' => 0]);
$fatture_vendita = Fattura::whereBetween('data', [$start, $end])
->where('idanagrafica', $id_record)
->whereHas('tipo', fn($query) => $query->where('co_tipidocumento.dir', '=', 'entrata')
->whereHas('tipo', fn ($query) => $query->where('co_tipidocumento.dir', '=', 'entrata')
->where('co_tipidocumento.reversed', '=', 0))
->whereIn('id_segment', array_column($segmenti, 'id'))
->get();
$note_credito = Fattura::whereBetween('data', [$start, $end])
->where('idanagrafica', $id_record)
->whereHas('tipo', fn($query) => $query->where('co_tipidocumento.dir', '=', 'entrata')
->whereHas('tipo', fn ($query) => $query->where('co_tipidocumento.dir', '=', 'entrata')
->where('co_tipidocumento.reversed', '=', 1))
->get();
$totale_fatture_vendita = $fatture_vendita->sum('totale_imponibile') - $note_credito->sum('totale_imponibile');

View File

@ -8,15 +8,15 @@ use Rector\Set\ValueObject\LevelSetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([
__DIR__ . '/api',
__DIR__ . '/config',
__DIR__ . '/include',
__DIR__ . '/lib',
__DIR__ . '/modules',
__DIR__ . '/plugins',
__DIR__ . '/src',
__DIR__ . '/templates',
__DIR__ . '/update',
__DIR__.'/api',
__DIR__.'/config',
__DIR__.'/include',
__DIR__.'/lib',
__DIR__.'/modules',
__DIR__.'/plugins',
__DIR__.'/src',
__DIR__.'/templates',
__DIR__.'/update',
]);
// register a single rule
@ -24,6 +24,6 @@ return static function (RectorConfig $rectorConfig): void {
// define sets of rules
$rectorConfig->sets([
LevelSetList::UP_TO_PHP_81
LevelSetList::UP_TO_PHP_81,
]);
};

View File

@ -188,7 +188,7 @@ abstract class AppResource extends Resource implements RetrieveInterface, Create
protected function mapModifiedRecords($records)
{
if ($records instanceof Collection) {
return $records->mapToGroups(fn($item, $key) => [$item['id'] => $item])->toArray();
return $records->mapToGroups(fn ($item, $key) => [$item['id'] => $item])->toArray();
}
return array_reduce($records, function ($accumulator, $item) {

View File

@ -85,7 +85,7 @@ class Services
{
return self::getServiziAttivi()
->flatten(1)
->filter(fn($item) => isset($item['data_conclusione']) && Carbon::parse($item['expiration_at'])->greaterThan(Carbon::now()) && Carbon::parse($item['data_conclusione'])->lessThan($limite_scadenze));
->filter(fn ($item) => isset($item['data_conclusione']) && Carbon::parse($item['expiration_at'])->greaterThan(Carbon::now()) && Carbon::parse($item['data_conclusione'])->lessThan($limite_scadenze));
}
/**
@ -97,7 +97,7 @@ class Services
{
return self::getServiziAttivi()
->flatten(1)
->filter(fn($item) => isset($item['data_conclusione']) && Carbon::parse($item['data_conclusione'])->lessThan(Carbon::now()));
->filter(fn ($item) => isset($item['data_conclusione']) && Carbon::parse($item['data_conclusione'])->lessThan(Carbon::now()));
}
/**
@ -117,7 +117,7 @@ class Services
*/
public static function verificaRisorsaAttiva($servizio)
{
return self::isEnabled() && self::getRisorseAttive()->search(fn($item) => $item['name'] == $servizio) !== false;
return self::isEnabled() && self::getRisorseAttive()->search(fn ($item) => $item['name'] == $servizio) !== false;
}
/**
@ -130,7 +130,7 @@ class Services
public static function getRisorseInScadenza($limite_scadenze)
{
return self::getRisorseAttive()
->filter(fn($item) => (isset($item['expiration_at']) && Carbon::parse($item['expiration_at'])->greaterThan(Carbon::now()) && Carbon::parse($item['expiration_at'])->lessThan($limite_scadenze))
->filter(fn ($item) => (isset($item['expiration_at']) && Carbon::parse($item['expiration_at'])->greaterThan(Carbon::now()) && Carbon::parse($item['expiration_at'])->lessThan($limite_scadenze))
|| (isset($item['credits']) && $item['credits'] < 100));
}
@ -142,7 +142,7 @@ class Services
public static function getRisorseScadute()
{
return self::getRisorseAttive()
->filter(fn($item) => (isset($item['expiration_at']) && Carbon::parse($item['expiration_at'])->lessThan(Carbon::now()))
->filter(fn ($item) => (isset($item['expiration_at']) && Carbon::parse($item['expiration_at'])->lessThan(Carbon::now()))
|| (isset($item['credits']) && $item['credits'] < 0));
}

View File

@ -168,7 +168,7 @@ class Auth extends Util\Singleton
// Salvataggio dello stato corrente
$log['stato'] = self::getStatus()[$status]['code'];
$log['user_agent'] = \Filter::getPurifier()->purify($_SERVER['HTTP_USER_AGENT']);
$log['user_agent'] = Filter::getPurifier()->purify($_SERVER['HTTP_USER_AGENT']);
$this->current_status = $status;
// Salvataggio del tentativo nel database

View File

@ -67,7 +67,7 @@ abstract class Document extends Model implements ReferenceInterface, DocumentInt
->get(),
])->flatten();
return $riferimenti->reject(fn($item) => empty($item->original_document_type))->unique(fn($item) => $item->original_document_type.'|'.$item->original_document_id)->mapToGroups(fn($item) => [$item->original_document_type => ($item->original_document_type)::find($item->original_document_id)]);
return $riferimenti->reject(fn ($item) => empty($item->original_document_type))->unique(fn ($item) => $item->original_document_type.'|'.$item->original_document_id)->mapToGroups(fn ($item) => [$item->original_document_type => ($item->original_document_type)::find($item->original_document_id)]);
}
/**
@ -79,7 +79,7 @@ abstract class Document extends Model implements ReferenceInterface, DocumentInt
{
$results = $this->mergeCollections($this->descrizioni, $this->righe, $this->articoli, $this->sconti);
return $results->sortBy(fn($item) => [$item->order, $item->id]);
return $results->sortBy(fn ($item) => [$item->order, $item->id]);
}
/**
@ -89,7 +89,7 @@ abstract class Document extends Model implements ReferenceInterface, DocumentInt
{
$righe = $this->getRighe();
return $righe->first(fn($item) => $item instanceof $type && $item->id == $id);
return $righe->first(fn ($item) => $item instanceof $type && $item->id == $id);
}
/**

View File

@ -55,7 +55,7 @@ abstract class CSVExporter implements ExporterInterface
public function setHeader()
{
$fields = $this->getAvailableFields();
$header = array_map(fn($item) => $item['label'], $fields);
$header = array_map(fn ($item) => $item['label'], $fields);
return $this->csv->insertOne($header);
}

View File

@ -45,7 +45,7 @@ class FileLoader extends \Symfony\Component\Translation\Loader\FileLoader
if (!empty($this->include_filename)) {
$result = array_combine(
array_map(fn($k) => basename($resource, '.'.$extension).'.'.$k, array_keys($result)),
array_map(fn ($k) => basename($resource, '.'.$extension).'.'.$k, array_keys($result)),
$result
);
}

View File

@ -107,7 +107,7 @@ class Module extends Model
$group = \Auth::user()->group->id;
$pivot = $this->pivot ?: $this->groups->first(fn($item) => $item->id == $group)->pivot;
$pivot = $this->pivot ?: $this->groups->first(fn ($item) => $item->id == $group)->pivot;
return $pivot->permessi ?: '-';
}

View File

@ -67,7 +67,7 @@ trait LocalPoolTrait
}
// Ricerca
$result = self::$collection->first(fn($item) => $item->{self::$name} == $identifier || $item->{self::$id} == $identifier);
$result = self::$collection->first(fn ($item) => $item->{self::$name} == $identifier || $item->{self::$id} == $identifier);
if (!empty($result)) {
return $result;

View File

@ -210,7 +210,7 @@ class Update
// Normalizzazione di charset e collation
self::normalizeDatabase($database->getDatabaseName());
if (class_exists(\Models\Cache::class)) {
if (class_exists(Cache::class)) {
Cache::find((new Cache())->getByField('name', 'Ultima versione di OpenSTAManager disponibile', Models\Locale::getPredefined()->id))->set(null);
}

View File

@ -547,23 +547,23 @@ if ($options['checklist']) {
echo renderChecklistHtml($check);
}
$impianti_collegati = $dbo->fetchArray('SELECT * FROM my_impianti_interventi INNER JOIN my_impianti ON my_impianti_interventi.idimpianto = my_impianti.id WHERE idintervento = '.prepare($id_record));
foreach ($impianti_collegati as $impianto) {
$checks = Check::where('id_module_from', (new Module())->getByField('name', 'Impianti', Models\Locale::getPredefined()->id))->where('id_record_from', $impianto['id'])->where('id_module', (new Module())->getByField('name', 'Interventi', Models\Locale::getPredefined()->id))->where('id_record', $id_record)->where('id_parent', null)->get();
if (sizeof($checks)) {
echo '
$impianti_collegati = $dbo->fetchArray('SELECT * FROM my_impianti_interventi INNER JOIN my_impianti ON my_impianti_interventi.idimpianto = my_impianti.id WHERE idintervento = '.prepare($id_record));
foreach ($impianti_collegati as $impianto) {
$checks = Check::where('id_module_from', (new Module())->getByField('name', 'Impianti', Models\Locale::getPredefined()->id))->where('id_record_from', $impianto['id'])->where('id_module', (new Module())->getByField('name', 'Interventi', Models\Locale::getPredefined()->id))->where('id_record', $id_record)->where('id_parent', null)->get();
if (sizeof($checks)) {
echo '
<tr>
<th class="text-center" colspan="2" style="font-size:11pt;">
<b>'.tr('Impianto', [], ['upper' => true]).' '.$impianto['matricola'].' - '.$impianto['nome'].'</b>
</th>
</tr>';
foreach ($checks as $check) {
echo renderChecklistHtml($check);
foreach ($checks as $check) {
echo renderChecklistHtml($check);
}
}
}
}
echo '
echo '
</table>';
}
}

View File

@ -45,7 +45,7 @@ if (!setting('Visualizza riferimento su ogni riga in stampa')) {
$columns = 7;
$has_image = $righe->search(fn($item) => !empty($item->articolo->immagine)) !== false && $options['images'] == true;
$has_image = $righe->search(fn ($item) => !empty($item->articolo->immagine)) !== false && $options['images'] == true;
if ($has_image) {
++$columns;

View File

@ -54,7 +54,7 @@ if ($pagamento && $pagamento->isRiBa()) {
// Righe documento
$righe = $documento->getRighe();
$has_image = $righe->search(fn($item) => !empty($item->articolo->immagine)) !== false && $options['images'] == true;
$has_image = $righe->search(fn ($item) => !empty($item->articolo->immagine)) !== false && $options['images'] == true;
$columns = $options['no-iva'] ? 5 : 6;
$columns = $options['pricing'] ? $columns : 3;

View File

@ -6,7 +6,7 @@ use Modules\Fatture\Gestori\Movimenti as GestoreMovimenti;
// Correzione movimenti contabili automatici per Fatture dalla versione 2.4.17 in poi
$fatture = Fattura::where('created_at', '>', '2020-08-01')
->whereHas('stato', fn($query) => $query->whereNotIn('descrizione', ['Bozza', 'Annullata']))
->whereHas('stato', fn ($query) => $query->whereNotIn('descrizione', ['Bozza', 'Annullata']))
->get();
foreach ($fatture as $fattura) {