Skip to main content

Libreria Python Consultazione DB GAzie

Client Python per consultare (e aggiornare) il DB GAzie tramite php-crud-api.

Questa pagina è la guida d'uso completa.

Installazione

pip install py_gazie

Pubblicazione con Jenkins

La pipeline in Jenkinsfile esegue make test e make build. Su master interroga PyPI e pubblica il pacchetto solo quando la versione dichiarata in setup.py non e' ancora disponibile; una versione gia' pubblicata viene saltata.

La configurazione del job e della credenziale con il token API sono descritte in docs/JENKINS_PYPI.md.

Uso rapido

from py_gazie import GazieClient

with GazieClient("http://127.0.0.1:8082/modules/api/index.php", "test-token",
                 timeout=15, default_company="001") as client:

    product = client.get_table("product")       # alias -> ProductTable (gaz_001artico)
    resp = product.page(limit=5).search()       # chaining: prima i filtri/pagina, poi search()

    if resp.success:                            # controlla SEMPRE success
        for rec in resp.data.records:           # NavigableRecord: attributi, non .get()
            print(rec.codice, "-", rec.descri)
        print("totale:", resp.data.pagination.total_records)
    else:
        print("errore:", resp.status_code, resp.error)

Le tabelle: cosa passare a get_table()

Vuoi Passa Ricevi Sul wire
clienti "customer" CustomerTable gaz_{company}clfoco
articoli "product" ProductTable gaz_{company}artico
anagrafiche fiscali "anagra" AnagraTable gaz_anagra
aziende "company" CompanyTable gaz_aziend
documenti di fatturazione (testata) "document" DocumentTable gaz_{company}tesdoc
altre tabelle nome reale, es. "gaz_001catmer" GazieTable generica stesso nome
  • Solo gli alias attivano i metodi di dominio (insert_record, get_by_code, search_by_description, get_rows, get_customer…): il nome reale dà sempre la tabella generica.
  • Tabella inesistente (o company non presente sul server) → ValueError con il nome della tabella mancante.
  • Le tabelle sono cachate: stessa company+nome → stessa istanza. La company esplicita vince su default_company; entrambe sono normalizzate a 3 cifre (2 → '002').

Classe GazieTable — operazioni

Tutte le tabelle (alias e generiche) hanno lo stesso nucleo: create · update · delete · get_by_id · search · first · count · exists · add_filter · order_by. Schema del chaining:

t = client.get_table("customer")
t.and_filter("codice", "sw", "103")     # AND (ripeti per aggiungere)
t.or_filter("descri", "cs", "Fermi")    # OR (filter1/filter2)
t.add_filter("or", "descri,cs,Fermi")   # stessa cosa da stringa 'campo,op,valore'
t.page(1, 10).order_by("codice,desc")   # pagina + ordinamento (order_by = alias di order)
resp = t.search()                       # -> ApiResponse

resp = t.read()                         # lista | t.read(item_id) -> record singolo
resp = t.get_by_id(42)                  # UN record per chiave primaria -> ApiResponse
resp = t.first()                        # primo record o None
n    = t.count()                        # totale filtrato (misurato:14 su artico)
ok   = t.exists()                       # almeno uno?
resp = t.create({...}) / t.update(id, {...}) / t.delete(id)

⚠️ I filtri si accumulano sull'istanza e vengono azzerati solo quando leggi: mai lasciare filtri appesi senza chiamare search()/read().

Operatori di filtro (misurati sul server, 22/09/2026)

  • ✅ eq, neq, gt, sw (inizia per), cs (contiene), in (valori separati da ,)
  • ❌ lk viene ignorato dal server (restituisce tutto): usa cs
  • AND = filter ripetuto · OR = filter1/filter2 · misto = intersezione
  • niente virgole nei valori: il filtro è la stringa "campo,op,valore"

Formato della risposta

Ogni operazione ritorna un ApiResponse con quattro campi: success, status_code, data, error.

Cosa manda il server Come si legge in data
elenco {"records": [...], "results": N} PaginatedData: resp.data.records (lista), len(resp.data), resp.data.pagination.total_records
record singolo dict grezzo: resp.data["codice"]
errore (es. 404, code 1003) success=False, error="Record … not found"
warning PHP (colonna inesistente) ⚠️ success=True ma data è una stringa HTML: controlla il tipo

I record dei elenchi sono NavigableRecord: accesso per attributo (rec.codice, rec.indirizzo.citta per i campi annidati). Non esiste rec.get("codice").

resp = client.get_table("product").page(limit=5).search()
if resp.success and hasattr(resp.data, "records"):
    for rec in resp.data.records:
        print(rec.codice, rec.descri)

Cinque regole d'oro

  1. Controlla sempre resp.success — gli errori HTTP/rete diventano success=False, niente eccezioni.
  2. Record dagli elenchi → attributi (rec.campo), mai .get().
  3. I metodi dichiarati -> List[…] in realtà ritornano ApiResponse: leggi resp.data.records.
  4. Mai lk nei filtri (ignorato dal server): cs = contiene, eq = uguale.
  5. create() completa da solo il payload: legge lo schema create-{t} da /openapi e valorizza tutte le colonne tranne id (autoincrement, tornato come resp.data) — tu passi solo quelle che ti servono. Puoi passare datetime.date/datetime/Decimal: vengono convertiti in stringhe (formato server YYYY-MM-DD HH:MM:SS), perché json.dumps non accetta oggetti. company non è una colonna: non va nel payload.
  6. Su customer il codice lo calcola la libreria (progressivo mascli di gaz_aziend): create() e insert_record() ignorano il codice che passi e generano il prossimo del mastro (es. 103000009), riprovando se il server risponde 409 Duplicate key.

Adattare GAzie a CRUD PHP API

Per adattare il database GAzie a php-crud-api occorre inserire il campo id come chiave primaria ove non vi sia (php-crud-api lo richiede per gli URL /records/{tabella}/{id}).

Procedura da eseguire sul DB GAzie

DELIMITER //

DROP PROCEDURE IF EXISTS AddIdPrimaryKeyToGazie //

CREATE PROCEDURE AddIdPrimaryKeyToGazie()
BEGIN
    -- =========================================================================
    -- 1. TUTTE LE DICHIARAZIONI (Devono stare in cima)
    -- =========================================================================
    DECLARE done INT DEFAULT FALSE;
    DECLARE current_table VARCHAR(255);
    DECLARE old_pk_columns VARCHAR(512);
    
    -- Cursore per escludere tabelle con 'id' o con qualsiasi altro AUTO_INCREMENT
    DECLARE table_cursor CURSOR FOR 
        SELECT t.TABLE_NAME 
        FROM information_schema.TABLES t
        WHERE t.TABLE_SCHEMA = DATABASE()
          AND t.TABLE_NAME LIKE 'gaz_%'
          AND NOT EXISTS (
              SELECT 1 
              FROM information_schema.COLUMNS c 
              WHERE c.TABLE_SCHEMA = DATABASE() 
                AND c.TABLE_NAME = t.TABLE_NAME 
                AND c.COLUMN_NAME = 'id'
          )
          AND NOT EXISTS (
              SELECT 1 
              FROM information_schema.COLUMNS c 
              WHERE c.TABLE_SCHEMA = DATABASE() 
                AND c.TABLE_NAME = t.TABLE_NAME 
                AND c.EXTRA LIKE '%auto_increment%'
          );

    -- L'handler deve essere l'ultima cosa dichiarata
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;


    -- =========================================================================
    -- 2. ISTRUZIONI ESEGUIBILI
    -- =========================================================================
    
    -- Creazione della tabella temporanea per il LOG
    DROP TEMPORARY TABLE IF EXISTS temp_log_alter_tables;
    CREATE TEMPORARY TABLE temp_log_alter_tables (
        id INT AUTO_INCREMENT PRIMARY KEY,
        eseguito_alle TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        tabella_modificata VARCHAR(255),
        query_eseguita TEXT
    );

    OPEN table_cursor;

    read_loop: LOOP
        FETCH table_cursor INTO current_table;
        
        IF done THEN
            LEAVE read_loop;
        END IF;

        -- Recupera dinamicamente le colonne che compongono l'attuale chiave primaria
        SELECT GROUP_CONCAT(COLUMN_NAME SEPARATOR ', ')
        INTO old_pk_columns
        FROM information_schema.KEY_COLUMN_USAGE
        WHERE TABLE_SCHEMA = DATABASE()
          AND TABLE_NAME = current_table
          AND CONSTRAINT_NAME = 'PRIMARY';

        -- Se esiste una vecchia chiave primaria, procediamo
        IF old_pk_columns IS NOT NULL THEN
            
            SET @dynamic_sql = CONCAT(
                'ALTER TABLE `', current_table, '` ',
                'DROP PRIMARY KEY, ',
                'ADD COLUMN `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST, ',
                'ADD UNIQUE KEY `uk_', current_table, '_old_pk` (', old_pk_columns, ');'
            );

            -- Scrittura nel LOG
            INSERT INTO temp_log_alter_tables (tabella_modificata, query_eseguita) 
            VALUES (current_table, @dynamic_sql);

            -- Esecuzione della query
            PREPARE stmt FROM @dynamic_sql;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
            
        END IF;

    END LOOP;

    CLOSE table_cursor;
    
    -- 3. Stampa a schermo del risultato finale
    SELECT * FROM temp_log_alter_tables;
    
    -- Pulizia finale
    DROP TEMPORARY TABLE IF EXISTS temp_log_alter_tables;

END //

DELIMITER ;

Chiamare la procedura

CALL AddIdPrimaryKeyToGazie();

Metadata

Release files for py-gazie 0.1.10

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for py-gazie 0.1.10
File Size Uploaded
py_gazie-0.1.10.tar.gz 87.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for py-gazie 0.1.10
File Interpreter ABI Platform
py_gazie-0.1.10-py3-none-any.whl Python 3 none any Details

Total release size: 217.1 kB

Release files / py_gazie-0.1.10.tar.gz

Download URL py_gazie-0.1.10.tar.gz
Size 87.4 kB
Tags Source
SHA-256 checksum
How to use checksums
bcb93d77c77592eaeff1d10c3fabdd6103eb817e7b4dfe36444bf332d832bebd
BLAKE2b-256 checksum
How to use checksums
f0c34cae140e21a841677cfe7da1f1a94171b0c4d0d20343972a21c49007501d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.5

Release files / py_gazie-0.1.10-py3-none-any.whl

Download URL py_gazie-0.1.10-py3-none-any.whl
Size 129.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a86673e371f1f30a8d7288b58a31171477e8a0610677c1ad1c1667d3fd6c046c
BLAKE2b-256 checksum
How to use checksums
c5812343b00171e2b633ccaf4a4e39019fca1d1474b740bb239f62e0fc3b6851
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.5

Release history Release notifications | RSS feed

This release

0.1.10 This release

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page