Operare zilnică
După ce un client e activ, fluxul operațional zilnic se învârte în jurul facturilor electronice din SFS (SIA „e-Factura”) și al task-urilor fiscale recurente. ASYDATA sincronizează automat facturile, le împinge ca carduri în Telegram, ține o aprobare internă separată de SFS și permite semnarea MSign cu auto-postare la SFS. Pagina descrie pas cu pas actorii și automatizările.
Corespondentul vizual (swimlane) e pe board-ul FigJam: ASYDATA pe Figma.
- ASYDATA (System) — worker-ul de polling e-Factură + WebApi.
- SFS / e-Factura (SPV) — sursa facturilor electronice.
- Firma de contabilitate — responsabilul care aprobă/semnează din Telegram sau din aplicație.
- Telegram — canalul unde apare cardul facturii.
- MSign — semnătura electronică, cu auto-postare la SFS.
Sincronizarea e-Factură (automat, ~20 min)
Secțiune intitulată „Sincronizarea e-Factură (automat, ~20 min)”Un worker rulează periodic (interval TimeSpan.FromMinutes(20), deci ~20 min) pentru fiecare firmă cu
credențiale SFS active. Logica de sincronizare e în EfacturaService.SyncInvoicesAsync
(asydata-app-backend-dotnet/src/Asy.Infrastructure/Efactura/EfacturaService.cs):
- Discovery —
SearchInvoices. Caută la SFS dupăActorRole(1 = furnizor/seller, 2 = cumpărător/buyer) și după codurile de status, deduplicând pe(Seria, Number)și păstrând statusul cel mai avansat. - Conținut —
GetInvoicesBySeriaNumber. Aduce XML-ul brut, parsat cuEfacturaXmlParser(supplier, buyer, linii, TVA). - Upsert
PartnerMaster. Partenerul se caută/creează după IDNO, cuPartnerRelationshipși conturi contabile implicite (incoming: Db521.1; outgoing: Db221.1/ Cr611.1). - Salvare fișiere în MinIO. XML (
{firmId}/{seria}-{number}.xml) și PDF dinGetInvoicesContentForPrint({firmId}/{seria}-{number}.pdf). Cheile se păstrează peInvoice.EFacturaXmlObjectKey/EFacturaPdfObjectKey. - Creează
Invoice(asydata-app-backend-dotnet/src/Asy.Domain/Invoicing/Invoice.cs), cuDirection(Incoming/Outgoing),EFacturaSfsStatus(codul brut SFS),EFacturaStatus(enum mapat) șiImportedFromSpvAt.
Codurile de status SFS
Secțiune intitulată „Codurile de status SFS”Invoice.EFacturaSfsStatus păstrează codul exact din SPV. Înțelesurile (din documentația modulului și din cod):
| Cod | Înțeles | Observații |
|---|---|---|
1 | Semnat de furnizor | facturile emise apar semnate de furnizor |
3 | Acceptat | cumpărătorul a acceptat |
4 | Anulat | status „prioritar” — câștigă la deduplicare; Invoice.Status = Cancelled |
6 | Arhivat | |
7 | Trimis | ciclu lung — facturile primite în acest status declanșează cardul Telegram |
8 | Semnat de cumpărător | la ciclu scurt, status informativ |
10 | Transportat |
Evenimentul → cardul Telegram
Secțiune intitulată „Evenimentul → cardul Telegram”Sincronizarea nu apelează direct Telegram. Pentru o factură primită relevantă, Invoice.RaiseEFacturaReceived(...)
ridică un eveniment de domeniu care trece prin outbox → Kafka firm.events → consumeri (Telegram, web push).
Consumerul Telegram postează un card cu butoane. Vezi flux event-driven și
integrarea Telegram.
Butoanele cardului (renderate de EfacturaCardRenderer):
- Aprobă / Respinge (
approve/decline) — doar dacă factura nu e ciclu scurt. - Vezi PDF (
pdf) și Vezi atașamentul (attach, dacă există). - Semnează (MSign) — buton URL (nu callback), spre endpoint-ul care inițiază semnarea.
- Plătește (
queue) — pune plata în coadă.
Aprobarea internă (NU atinge SFS)
Secțiune intitulată „Aprobarea internă (NU atinge SFS)”Aprobarea internă e separată de statusul SFS. Responsabilul apasă Aprobă/Respinge în card, iar serviciul
apelează Invoice.ApproveInternally(...) / Invoice.RejectInternally(...):
InternalApprovalStatus | Înțeles |
|---|---|
Pending | tocmai primită — așteaptă decizia responsabilului |
Approved | aprobată intern → poate fi apoi semnată (MSign) la SFS |
Rejected | respinsă intern |
Semnarea MSign → PostInvoices la SFS
Secțiune intitulată „Semnarea MSign → PostInvoices la SFS”Când factura aprobată se semnează prin MSign, cererea de semnătură (MsignRequest,
asydata-app-backend-dotnet/src/Asy.Domain/Msign/MsignRequest.cs) primește un PostBackTarget de forma
efactura:postinvoices:<actorRole>. La succesul callback-ului MSign:
- XML-ul semnat se postează automat la SFS prin
PostInvoices(actor role furnizor1pentru outgoing, cumpărător2pentru incoming). Invoice.EFacturaStatustrece spreSentToEFactura/Accepted,EFacturaRefse completează, iarEFacturaSignedByNamese setează din certificat.- Răspunsul SFS se salvează în
MsignRequest.PostBackResultpentru audit.
Re-editarea cardului
Secțiune intitulată „Re-editarea cardului”Când statusul SFS al unei facturi se schimbă în afara aplicației (semnat/respins/anulat în portalul SPV), o
sincronizare ulterioară apelează Invoice.RaiseEFacturaStatusChanged() → eveniment → consumerul Telegram
re-editează cardul existent (nu trimite un mesaj nou).
Task-uri recurente (declarații fiscale)
Secțiune intitulată „Task-uri recurente (declarații fiscale)”Separat de facturi, munca lunară (declarații fiscale, raportări) se materializează din reguli recurente.
RecurringTaskRule (asydata-app-backend-dotnet/src/Asy.Domain/Tasks/RecurringTaskRule.cs) definește o regulă
per client, cu Frequency (RecurringFrequency { Daily, Weekly, Monthly }), DayOfMonth, TimeOfDay
(implicit 09:00), Timezone ("Europe/Chisinau").
Serviciul RecurringTaskRulesService (asydata-app-backend-dotnet/src/Asy.Infrastructure/Tasks/RecurringTaskRulesService.cs)
generează câte un TaskItem la fiecare rulare (copiind titlu, descriere, prioritate, asignați impliciți),
apoi actualizează LastRunAt, LastGeneratedTaskId, TotalGeneratedCount și recalculează NextRunAt.
Task-ul rezultat (asydata-app-backend-dotnet/src/Asy.Domain/Tasks/TaskItem.cs) parcurge:
TaskItemStatus | Înțeles |
|---|---|
Todo | de făcut (implicit la creare) |
Doing | în lucru |
PendingReview | așteaptă revizuire (când RequiresReview) |
Done | finalizat |
Cancelled | anulat |
Prioritatea e TaskItemPriority { Low, Normal, High, Urgent }.
- Stări și lifecycle — toate enum-urile, inclusiv codurile SFS.
- Comunicare și semnare — detalii despre carduri și butoanele lor.
- Integrarea e-Factura / SFS și MSign.
- Flux event-driven — outbox → Kafka → consumeri.