Dominio inv β Panoramica sviluppatore
π― Cosa faβ
Il dominio inv gestisce la fatturazione elettronica FatturaPA:
emissione, trasmissione via Aruba al Sistema di Interscambio,
tracciamento stati, piano rate e convenzioni commerciali.
πΊοΈ Mappa moduliβ
Database β TrainingHub.Database/inv/β
| File | Ruolo |
|---|---|
Tables/issuers.sql | Emittenti (cedente/prestatore + credenziali Aruba) |
Tables/bankAccounts.sql | Anagrafica conti bancari per emittente |
Tables/invoices.sql | Intestazione fattura |
Tables/invoiceLines.sql | Righe di dettaglio |
Tables/invoicePayments.sql | Piano rate |
Tables/invoiceAppointments.sql | Associazione N:N fattura β appuntamenti formativi |
Tables/invoiceStatusHistory.sql | Storico cambi di stato |
Tables/conventions.sql | Convenzioni (sconto per categoria corso) |
Tables/companyConventions.sql | Associazione N:N azienda β convenzione |
Tables/vatCodes.sql | Codici IVA riutilizzabili |
Tables/paymentMethods.sql | Lookup codici metodo pagamento SDI (MP01βMP23) |
Tables/documentTypes.sql | Lookup codici tipo documento SDI (TD01βTD28) |
Functions/fn_activeConventions.sql | TVF: convenzioni attive per (companyId, issueDate) |
Service layer β TrainingHub.BackOffice/Services/Invoicing/β
| File | Ruolo |
|---|---|
IInvoiceService.cs | Interfaccia servizio fattura |
InvoiceService.cs | Implementazione + integrazione Aruba |
UI CRUD β TrainingHub.BackOffice/Components/CRUD/inv/β
Nove entitΓ CRUD auto-generate. Pattern per ciascuna:
<Entity>.razor+.razor.tt.cs(grid autogenerata)<Entity>.razor.cs(code-behind custom)Forms/<Entity>Form.razor+.razor.cs+.razor.tt.csFormPopups/<Entity>FormPopup.razor+.razor.cs+.razor.tt.cs
EntitΓ presenti:
Invoice(con wizard 5 passi inFormPopups/InvoiceFormPopup.razor.cs)InvoiceLine,InvoicePayment,InvoiceAppointment,InvoiceStatusHistoryIssuer,VatCode,PaymentMethod,DocumentTypeBankAccountConvention,CompanyConvention
Configurazione CRUD β _conf/*.dxgrid.conf.jsonβ
Un file JSON per entitΓ che guida la generazione. Modificare qui per
cambi persistenti; i file .razor e .razor.tt.cs vengono rigenerati
dal tool MCP 3sd-generator.
Test β TrainingHub.Tests/Services/Invoicing/β
InvoiceServiceTests.cs β copertura InvoiceService (numerazione,
invio, storico, piano rate).
π§ API pubblica β IInvoiceServiceβ
Task<int> GetNextInvoiceNumberAsync(Guid issuerId, int year, CancellationToken ct);
static string BuildInvoiceCode(int year, int number, string? sezionale = null);
Task SendToArubaAsync(Guid invoiceId, CancellationToken ct);
Task RefreshStatusFromArubaAsync(Guid invoiceId, CancellationToken ct);
Task AddStatusHistoryAsync(Guid invoiceId, InvoiceStatus status, string? arubaStatus, string? notes, string? createdBy, CancellationToken ct);
Task<IEnumerable<invoiceStatusHistory>> GetStatusHistoryAsync(Guid invoiceId, CancellationToken ct);
Task<IEnumerable<invoicePayment>> GetPaymentsAsync(Guid invoiceId, CancellationToken ct);
Task SavePaymentsAsync(Guid invoiceId, IEnumerable<invoicePayment> payments, CancellationToken ct);
Registrato in Program.cs nella sezione DI.
π§© Pattern chiaveβ
Wizard fatturaβ
Il form di edit della fattura Γ¨ un wizard a 5 step realizzato in
FormPopups/InvoiceFormPopup.razor + .razor.cs, usando
Tabiot.Blazor.Wizard.Wizard. Sequenza step e hook OnStepChange:
| Step | Titolo | Hook |
|---|---|---|
| 1 | Dati fattura | SaveInvoiceDraft |
| 2 | Appuntamenti | CreateLinesFromAppointments |
| 3 | Righe | β |
| 4 | Pagamenti | SavePayments (valida somma = 100%) |
| 5 | Riepilogo | LoadSummary (totali + storico + pulsanti SDI) |
Generazione CRUDβ
I file .razor e .razor.tt.cs sono rigenerati dal tool MCP
3sd-generator a partire dallo schema DB e dal conf.json. Modifiche
dirette in questi file vanno perse alla rigenerazione: per rendere
persistenti le modifiche aggiornare il conf.json e rigenerare.
Il code-behind .razor.cs contiene il codice custom e non viene
toccato dalla generazione.
Applicazione convenzioniβ
Al momento dell'emissione fattura, CreateLinesFromAppointments (in
InvoiceFormPopup.razor.cs) usa inv.fn_activeConventions(companyId, issueDate) per recuperare lo sconto attivo e pre-popolare la riga con
il discountPercentage corretto.
Numerazioneβ
GetNextInvoiceNumberAsync calcola il prossimo progressivo con un
SELECT MAX(invoiceNumber) + 1 filtrato per issuerId e invoiceYear.
Il vincolo unique UQ_invoices_number(issuerId, invoiceYear, invoiceNumber) garantisce unicitΓ anche sotto race condition (il
secondo insert fallisce).
π¦ Dipendenzeβ
Brighela.SimpleCRUD.Service.ISimpleCRUDServiceβ CRUD di baseOss.Filtersβ filtri su gridTabiot.Blazor.*β wizard, grid, popup, comboDevExpress.Blazorβ componenti UIMicrosoft.Extensions.Localization.IStringLocalizer<T>β etichette localizzate- Ecosistema 3SD: Scarnas, Brighela, Servel, Ploc, Tabiot, Mulet
β οΈ Domande aperte / debito tecnicoβ
- Credenziali Aruba in chiaro.
inv.issuers.arubaPasswordè memorizzata in chiaro. Decisione esplicita a design (back-office interno), ma valutare cifratura simmetrica con chiave da config per compliance futura. - Job schedulato di refresh stato fatture inviate. Oggi il refresh è solo manuale via pulsante. Da implementare come hosted service.
- Tipo documento (fattura / nota di credito / acconto) non
presente in
inv.invoices. Oggi distinzione solo per segno importi. Aggiungere campo esplicito per allineamento FatturaPA.
π Vedi ancheβ
- Schema DB β dettaglio tabelle, FK, indici
- Componenti UI β struttura Blazor CRUD
- Servizi β logica
InvoiceService - Aggiungere un campo β tutorial
- Guida utente: Panoramica fatturazione (docs-site-user)