# Sisteme externe și executori

Cum vorbește platforma cu FGO

## Modelul: coadă și executor

Platforma nu deschide singură conexiuni lungi spre sistemele externe. Lucrul se pune într-o **coadă**, iar un **executor** (un agent care rulează pe server, cu rolul `executor`) îl ia, îl face și raportează rezultatul.

```bash title="Ciclul unui executor"
GET  /v1/facturi-din-bon/coada                 # ce e de făcut
POST /v1/facturi-din-bon/coada/{id}/ia          # rezerv sarcina
POST /v1/facturi-din-bon/coada/{id}/rezultat    # raportez rezultatul
```

Avantajele modelului:

- o sarcină nu se pierde dacă sistemul extern cade: rămâne în coadă și se reia;
- executorul folosește un **jeton de serviciu**, niciodată sesiunea unui om;
- fiecare rezultat rămâne scris pe cerere, deci o eroare ulterioară nu șterge ce s-a făcut deja.

## Sistemele legate

| Sistem | Ce face platforma | Module |
| --- | --- | --- |
| FGO | facturare: produse, clienți, cote TVA, curs valutar, calculul liniei | `fgo` |
| SPV (ANAF e-Factura) | autorizarea firmei, sincronizarea facturilor primite, fișierele PDF și XML | `spv` |
| Google Drive | pozele produselor, printr-un canal verificat cu jeton | `hook-drive` |

### Alte sisteme găsite în cod

| Sistem | Ce face | Prin |
| --- | --- | --- |
| Pinterest | citește pinii contului la 5 minute și scrie bifa Pinterest în tabelul Produse; repunerea unui pin din copie are un mod separat, pe care timerul nu îl pornește | unitatea `pinterest-canal`, conexiunea în `tabel-produse` |
| Lark | doar pagina „Automatizări Lark”, încă fără date; nu există o legătură cu Lark în codul platformei | pagina `automatizari-lark` |
| Oglinda pe NAS | copiază la 2 minute ramura de cod pe NAS, doar fast-forward, fără force; o ramură deviată nu e atinsă | unitatea `oglinda-nas` |
| Finder, anunțuri | Storia, OLX, Publi24, Imobiliare, Anunțul, la 30 de minute, în `finder_anunturi` | `servicii/finder-colector`, modulul `finder` |
| Finder, joburi | BestJobs, eJobs, Hipo, OLX, Undelucram, MyJob, Romjob, la 6 ore | `servicii/finder-colector`, `finder-joburi` |
| Meta (Facebook, Instagram), TikTok | statisticile conturilor de social media, doar citire | executorul `social_statistici`, modulul `social` |
| Resend | trimiterea emailurilor (cod de intrare, resetare); cheia vine din mediu, pe firmă | `email`, `resetare` |
| Gemini | propunerile „Generează cu AI” din fișa produsului și rezerva asistentului | `meniu-ai`, `asistent` |
| Codex / ChatGPT | asistentul cu unelte și generarea imaginilor, prin două punți locale | `asistent`, `meniu-ai` |
| BNR | cursul valutar din XML-ul anual BNR, pentru facturi | `fgo` |
| FGO, sincronizarea registrului | la 30 de minute, citește FGO și scrie doar facturile Registrului | `servicii/registru-sync-fgo` |

Orele exacte ale fiecăruia sunt în [Ce rulează în fundal](#ce-ruleaza-in-fundal).

> [!NOTE]
> Rutele FGO sunt doar de citire și cer rolul `admin`. Calculul unei linii de factură nu atinge baza de date.

## Regula 503: niciodată o listă goală

Când o sursă externă nu este configurată, lipsește sau trimite date în altă formă decât contractul, ruta răspunde cu `503` și un motiv. Nu răspunde niciodată cu o listă goală sau cu zero, ca să nu pară că firma „nu are nimic”.

```http title="Exemplu: stocul, când fișierul sursă lipsește"
HTTP/1.1 503 Service Unavailable

{"eroare": "stoc_indisponibil", "motiv": "fisier_lipsa", "fisier": "stoc.json"}
```

Fiecare modul își are codul lui (`stoc_indisponibil`, `receptii_indisponibile`, `sursa_neconfigurata`); câmpul `motiv` apare acolo unde modulul știe cauza.

## Rutele cu verificare proprie

Două rute au acces `intern`: dovada nu este o sesiune, ci o verificare făcută chiar de modul (de exemplu jetonul canalului Google Drive la `POST /hook/drive`). Ele nu se folosesc din aplicații obișnuite.
