Skip to content

Il selettore "sedi_azienda" filtra an_sedi per id anziché id_anagrafica: le sedi secondarie dell'azienda non compaiono (Giacenze sedi e altri selettori) #1920

Description

@lincetto

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

  1. Azienda predefinita con almeno una sede aggiuntiva in an_sedi (id_anagrafica = <id_azienda>) la cui PK id sia diversa da <id_azienda>.
  2. Andare in Magazzino → Giacenze sedi.
  3. 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:

  1. Nella $query, cambiare FROM \an_sedi` |where|inFROM `an_sedi` |where_sedi|`.
  2. 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

  • OSM: 2.11-beta

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions