Services & Adapters

FogliPostgrestService

Service PostgREST per CRUD fogli, versioni, ACL, catalogo sorgenti ERP. Gestisce header schema profile e parsing errori PostgREST.

Costruttore

class FogliPostgrestService {
  constructor(private readonly baseUrl: string)
}

Service per le operazioni CRUD sullo schema PostgreSQL foglidicalcolo. Tutte le richieste includono header schema profile:

Accept-Profile: foglidicalcolo
Content-Profile: foglidicalcolo

API

listaFogli(filters)

async listaFogli(filters: FoglioFilters): Promise<PaginatedResult<FoglioDiCalcolo>>

Lista paginata. Se filters.searchText è non vuoto, usa v_foglidicalcolo_ricerca con tsv_search=plfts(italian).{q}. Altrimenti v_foglidicalcolo_lista.

Filtri tradotti in query string:

filters.tipoQuery
'mine'permesso_effettivo=eq.proprietario
'shared'permesso_effettivo=neq.proprietario
'templates'istemplate=eq.true
'all'(nessun filtro aggiuntivo)

Paginazione tramite header Range: 0-{end} + Prefer: count=exact. Risposta include Content-Range per il totale.

caricaFoglio(idfolio)

async caricaFoglio(idfolio: number): Promise<FoglioDettaglio | null>

GET su una vista di dettaglio del foglio (metadati + filtriglobali + sorgentierp + info lock). Ritorna null se il foglio non esiste (PostgREST 406 PGRST116).

creaFoglio(request)

async creaFoglio(request: CreateFoglioRequest): Promise<FoglioDettaglio>

POST /foglidicalcolo con Prefer: return=representation. Ritorna il foglio creato con idfolio valorizzato.

aggiornaDati(idfolio, request)

async aggiornaDati(idfolio: number, request: UpdateFoglioRequest): Promise<FoglioDettaglio>

PATCH /foglidicalcolo?idfolio=eq.{id} con Prefer: return=representation. Usato per:

  • rinomina (nome)
  • aggiornare descrizione/flag template/pubblico
  • salvare filtriglobali
  • aggiornare sorgentierp

eliminaFoglio(idfolio)

async eliminaFoglio(idfolio: number): Promise<boolean>

Elimina il foglio. L'implementazione può usare RPC elimina_foglio o DELETE diretto. Cascade del DB pulisce versioni e ACL associate.

duplicaFoglio(idfolio)

async duplicaFoglio(idfolio: number): Promise<number>

RPC POST /rpc/duplica_foglio con { p_idfolio }. Ritorna idfolio del foglio duplicato.

Il duplicato:

  • copia metadati, filtriglobali, sorgentierp
  • copia l'ultima versione come rev. 1 del nuovo foglio
  • imposta idproprietario = current_user
  • imposta nome = '{original.nome} (copia)'

listaVersioni(idfolio)

async listaVersioni(idfolio: number): Promise<FoglioVersioneSummary[]>

GET /foglidicalcoloversioni?idfolio=eq.{id}&order=numerorevisione.desc&select=idversione,idfolio,numerorevisione,idautore,datacreazione.

Non scarica lo snapshot — solo metadata. Lo snapshot è scaricato separatamente.

caricaUltimaVersione(idfolio)

async caricaUltimaVersione(idfolio: number): Promise<FoglioVersione | null>

Carica la versione corrente del foglio con snapshot. Usato all'apertura del foglio.

GET /foglidicalcoloversioni?idfolio=eq.{id}&order=numerorevisione.desc&limit=1
Accept: application/vnd.pgrst.object+json

Ritorna null se il foglio non ha ancora versioni (foglio appena creato).

salvaVersione(request)

async salvaVersione(request: SalvaVersioneRequest): Promise<FoglioVersione>

POST /foglidicalcoloversioni con Prefer: return=representation.

interface SalvaVersioneRequest {
  idfolio: number
  numerorevisione: number             // incrementale
  snapshot: FortuneSheetSnapshot
  idautore?: number                   // se omesso, DB usa _get_current_user_id()
}

ripristinaVersione(idversione)

async ripristinaVersione(idversione: number): Promise<number>

RPC POST /rpc/ripristina_versione_foglio con { p_idversione }. Ritorna idversione della nuova versione creata.

Il DB clona lo snapshot della versione passata come nuova versione corrente (non distrugge le versioni intermedie).

listaAcl(idfolio)

async listaAcl(idfolio: number): Promise<FoglioAcl[]>

GET /foglidicalcoloacl?idfolio=eq.{id}. Ritorna le righe ACL associate al foglio (escluso il proprietario, gestito a livello foglidicalcolo.idproprietario).

aggiungiAcl(idfolio, idutente, permesso)

async aggiungiAcl(
  idfolio: number,
  idutente: number,
  permesso: 'lettura' | 'scrittura',
): Promise<FoglioAcl>

POST /foglidicalcoloacl. Richiede che l'utente corrente sia proprietario (verificato server-side).

modificaAcl(idacl, permesso)

async modificaAcl(idacl: number, permesso: 'lettura' | 'scrittura'): Promise<FoglioAcl>

PATCH /foglidicalcoloacl?idacl=eq.{id}.

rimuoviAcl(idacl)

async rimuoviAcl(idacl: number): Promise<void>

DELETE /foglidicalcoloacl?idacl=eq.{id}.

async catalogo(): Promise<SorgenteCatalogo[]>

GET /foglidicalcolosorgenticatalogo?isattivo=eq.true&order=ordinamento.asc. Ritorna le sorgenti ERP attive nel catalogo.

Gestione errori PostgREST

Il service formatta gli errori PostgREST in modo human-readable:

PostgREST 406: PGRST116 — Cannot coerce the result to a single JSON object
PostgREST 403: insufficient_privilege — permission denied for table foglidicalcolo
PostgREST 400: 22P02 — invalid input syntax for type integer

Il messaggio combina status + (messagedetailshint) del JSON di risposta. Se il body non è JSON, usa il testo grezzo.

Header schema profile

Tutte le richieste verso lo schema foglidicalcolo richiedono:

Accept-Profile: foglidicalcolo
Content-Profile: foglidicalcolo

Il service li aggiunge automaticamente. Questo permette di esporre le tabelle in uno schema separato da quello pubblico, isolando il modello dati della feature.

Helper interni

Metodo privatoCosa fa
fetchJson<T>(endpoint, options)Wrapper fetch + JSON parse + error handling
formatPostgrestError(response)Parsing/formatting JSON errori PostgREST
parseTotaleFromContentRange(header)Estrae il totale da items 0-19/42

Tipi correlati