Passa al contenuto principale

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/​

FileRuolo
Tables/issuers.sqlEmittenti (cedente/prestatore + credenziali Aruba)
Tables/bankAccounts.sqlAnagrafica conti bancari per emittente
Tables/invoices.sqlIntestazione fattura
Tables/invoiceLines.sqlRighe di dettaglio
Tables/invoicePayments.sqlPiano rate
Tables/invoiceAppointments.sqlAssociazione N:N fattura ↔ appuntamenti formativi
Tables/invoiceStatusHistory.sqlStorico cambi di stato
Tables/conventions.sqlConvenzioni (sconto per categoria corso)
Tables/companyConventions.sqlAssociazione N:N azienda ↔ convenzione
Tables/vatCodes.sqlCodici IVA riutilizzabili
Tables/paymentMethods.sqlLookup codici metodo pagamento SDI (MP01–MP23)
Tables/documentTypes.sqlLookup codici tipo documento SDI (TD01–TD28)
Functions/fn_activeConventions.sqlTVF: convenzioni attive per (companyId, issueDate)

Service layer β€” TrainingHub.BackOffice/Services/Invoicing/​

FileRuolo
IInvoiceService.csInterfaccia servizio fattura
InvoiceService.csImplementazione + 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.cs
  • FormPopups/<Entity>FormPopup.razor + .razor.cs + .razor.tt.cs

EntitΓ  presenti:

  • Invoice (con wizard 5 passi in FormPopups/InvoiceFormPopup.razor.cs)
  • InvoiceLine, InvoicePayment, InvoiceAppointment, InvoiceStatusHistory
  • Issuer, VatCode, PaymentMethod, DocumentType
  • BankAccount
  • Convention, 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:

StepTitoloHook
1Dati fatturaSaveInvoiceDraft
2AppuntamentiCreateLinesFromAppointments
3Righeβ€”
4PagamentiSavePayments (valida somma = 100%)
5RiepilogoLoadSummary (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 base
  • Oss.Filters β€” filtri su grid
  • Tabiot.Blazor.* β€” wizard, grid, popup, combo
  • DevExpress.Blazor β€” componenti UI
  • Microsoft.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​