Descrizione
La fonte AJAX sedi_azienda (in modules/anagrafiche/ajax/select.php) filtra la tabella an_sedi per an_sedi.id = <id_azienda> invece che per an_sedi.id_anagrafica = <id_azienda>. Di conseguenza le sedi secondarie dell'azienda non vengono elencate nel selettore. Il caso più visibile è la tendina "Sede" del modulo Giacenze sedi, che non mostra le sedi aggiuntive dell'azienda.
Comportamento atteso
Il selettore elenca la "Sede legale" e tutte le sedi dell'azienda predefinita (an_sedi con id_anagrafica = <id_azienda> e deleted_at IS NULL).
Comportamento osservato
Le sedi aggiuntive dell'azienda non compaiono nella tendina. Al più compare una sede scorretta: quella la cui chiave primaria an_sedi.id coincide con <id_azienda>. Riscontrato in un caso reale: la sede visualizzata è addirittura una sede soft-deleted (deleted_at valorizzato) che ha, per coincidenza, an_sedi.id uguale all'id dell'azienda predefinita, mentre la sede nuova e valida (con id_anagrafica = <id_azienda> ma id diverso) non viene mai mostrata.
Causa
Nel case sedi_azienda la query è una UNION tra an_anagrafiche (Sede legale) e an_sedi, ma usa lo stesso placeholder |where| per entrambe le tabelle:
$query = "SELECT * FROM (SELECT '0' AS id, 'Sede legale' AS `nome_sede`, CONCAT_WS(... FROM `an_anagrafiche` |where|)) AS descrizione UNION SELECT `id`, `nome_sede`, CONCAT_WS(...) FROM `an_sedi` |where| ORDER BY `nome_sede`) AS tab |filter| ORDER BY descrizione";
$where[] = '`id`='.prepare($id_azienda);
$where[] = 'deleted_at IS NULL';
La sostituzione di |where| in AJAX::selectResults() è globale (str_replace('|where|', ...)), quindi la condizione id = <id_azienda> viene applicata anche ad an_sedi, che finisce filtrata per an_sedi.id = <id_azienda>. Ma an_sedi.id è la PK della sede, non il legame con l'azienda: il filtro corretto è an_sedi.id_anagrafica = <id_azienda>.
Poiché la parte an_sedi viene agganciata per PK, può emergere anche una sede soft-deleted: il guard deleted_at IS NULL finisce applicato al match per id sbagliato e non protegge correttamente la lista.
Regressione (2.11)
Fino alla 2.10.4 la condizione condivisa era:
$where[] = '`idanagrafica`='.prepare($id_azienda);
e funzionava per entrambe le tabelle perché sia an_anagrafiche sia an_sedi avevano la colonna idanagrafica. Nella 2.11, con il refactor che ha rinominato le colonne (an_anagrafiche PK → id, an_sedi FK → id_anagrafica), il case sedi_azienda è stato migrato solo a metà: idanagrafica → id sistema il lato an_anagrafiche ma rompe il lato an_sedi.
Nello stesso file, il case sedi è stato invece migrato correttamente, usando due placeholder distinti (|where_legale| per an_anagrafiche e |where_sedi| con id_anagrafica = ... per an_sedi). Il baco è presente in 2.11, 2.11.1 e master.
Come riprodurre
- Azienda predefinita con almeno una sede aggiuntiva in
an_sedi (id_anagrafica = <id_azienda>) la cui PK id sia diversa da <id_azienda>.
- Andare in Magazzino → Giacenze sedi.
- La tendina "Sede" non elenca quella sede.
Dimostrazione lato DB:
SELECT valore AS id_azienda FROM zz_settings WHERE nome = 'Azienda predefinita';
-- Ciò che la tendina esegue di fatto (SBAGLIATO): match per PK
SELECT id, nome_sede FROM an_sedi WHERE id = <id_azienda> AND deleted_at IS NULL;
-- Ciò che dovrebbe eseguire (CORRETTO): le sedi dell'azienda
SELECT id, nome_sede FROM an_sedi WHERE id_anagrafica = <id_azienda> AND deleted_at IS NULL;
Punti coinvolti
sedi_azienda è usata dal selettore "sede azienda" in vari moduli (Giacenze sedi, DDT, fatture, ordini, interventi, movimenti, articoli, ecc.), quindi il problema si riflette su tutti.
Proposta di correzione
Dare ad an_sedi un placeholder proprio, esattamente come già fa il case sedi. In sedi_azienda:
- Nella
$query, cambiare FROM \an_sedi` |where|inFROM `an_sedi` |where_sedi|`.
- Aggiungere, dopo le righe
$where[]:
$where_sedi[] = '`id_anagrafica`='.prepare($id_azienda);
$where_sedi[] = 'deleted_at IS NULL';
$query = str_replace('|where_sedi|', 'WHERE '.implode(' AND ', $where_sedi), $query);
Il |where| rimasto (parte an_anagrafiche) e |filter| continuano a essere sostituiti dalla logica generica. Così il selettore elenca correttamente tutte le sedi dell'azienda ed esclude quelle soft-deleted.
Ambiente
Descrizione
La fonte AJAX
sedi_azienda(inmodules/anagrafiche/ajax/select.php) filtra la tabellaan_sediperan_sedi.id = <id_azienda>invece che peran_sedi.id_anagrafica = <id_azienda>. Di conseguenza le sedi secondarie dell'azienda non vengono elencate nel selettore. Il caso più visibile è la tendina "Sede" del modulo Giacenze sedi, che non mostra le sedi aggiuntive dell'azienda.Comportamento atteso
Il selettore elenca la "Sede legale" e tutte le sedi dell'azienda predefinita (
an_sediconid_anagrafica = <id_azienda>edeleted_at IS NULL).Comportamento osservato
Le sedi aggiuntive dell'azienda non compaiono nella tendina. Al più compare una sede scorretta: quella la cui chiave primaria
an_sedi.idcoincide con<id_azienda>. Riscontrato in un caso reale: la sede visualizzata è addirittura una sede soft-deleted (deleted_atvalorizzato) che ha, per coincidenza,an_sedi.iduguale all'id dell'azienda predefinita, mentre la sede nuova e valida (conid_anagrafica = <id_azienda>maiddiverso) non viene mai mostrata.Causa
Nel case
sedi_aziendala query è una UNION traan_anagrafiche(Sede legale) ean_sedi, ma usa lo stesso placeholder|where|per entrambe le tabelle:La sostituzione di
|where|inAJAX::selectResults()è globale (str_replace('|where|', ...)), quindi la condizioneid = <id_azienda>viene applicata anche adan_sedi, che finisce filtrata peran_sedi.id = <id_azienda>. Maan_sedi.idè la PK della sede, non il legame con l'azienda: il filtro corretto èan_sedi.id_anagrafica = <id_azienda>.Poiché la parte
an_sediviene agganciata per PK, può emergere anche una sede soft-deleted: il guarddeleted_at IS NULLfinisce applicato al match peridsbagliato e non protegge correttamente la lista.Regressione (2.11)
Fino alla 2.10.4 la condizione condivisa era:
e funzionava per entrambe le tabelle perché sia
an_anagrafichesiaan_sediavevano la colonnaidanagrafica. Nella 2.11, con il refactor che ha rinominato le colonne (an_anagrafichePK →id,an_sediFK →id_anagrafica), il casesedi_aziendaè stato migrato solo a metà:idanagrafica→idsistema il latoan_anagrafichema rompe il latoan_sedi.Nello stesso file, il case
sediè stato invece migrato correttamente, usando due placeholder distinti (|where_legale|peran_anagrafichee|where_sedi|conid_anagrafica = ...peran_sedi). Il baco è presente in 2.11, 2.11.1 e master.Come riprodurre
an_sedi(id_anagrafica = <id_azienda>) la cui PKidsia diversa da<id_azienda>.Dimostrazione lato DB:
Punti coinvolti
sedi_aziendaè usata dal selettore "sede azienda" in vari moduli (Giacenze sedi, DDT, fatture, ordini, interventi, movimenti, articoli, ecc.), quindi il problema si riflette su tutti.Proposta di correzione
Dare ad
an_sediun placeholder proprio, esattamente come già fa il casesedi. Insedi_azienda:$query, cambiareFROM \an_sedi` |where|inFROM `an_sedi` |where_sedi|`.$where[]:Il
|where|rimasto (partean_anagrafiche) e|filter|continuano a essere sostituiti dalla logica generica. Così il selettore elenca correttamente tutte le sedi dell'azienda ed esclude quelle soft-deleted.Ambiente
2.11-beta