Case study 03

Licto: Monitorizare automată a licitațiilor SEAP

Sistem privat care trimite alerte doar pentru anunțurile relevante și urmărește termenele-limită.

Fluxul Licto: API-ul public SEAP, normalizare, scor și potrivire, listă de verificat și notificare, plus motivele scorului și monitorizarea rulărilor

Pe scurt

Licto urmărește zilnic anunțurile din SEAP și îi dă operatorului o listă scurtă cu licitațiile care contează pentru firmă.

Pentru fiecare rezultat arată de ce a fost selectat, urmărește termenele-limită și modificările lor și separă licitațiile active de semnalele timpurii. Sistemul își verifică singur și preluarea datelor.

Context

Datele există în portalul public. Problema este să afli rapid ce este nou, ce merită atenție, ce s-a schimbat și ce trebuie făcut astăzi.

Alertele pe cuvinte-cheie aduc prea multe rezultate, iar un scraper fragil se strică la prima schimbare din portal. Licto avea nevoie de o preluare stabilă, reguli adaptate fiecărui client și o interfață pe care echipa să o poată folosi fără ajutor tehnic.

Constrângeri

Sistemul trebuie să fie de încredere atât în zilele cu multe anunțuri, cât și în cele fără rezultate.

  • SEAP oferă date JSON utile, dar fără documentație oficială și fără garanția că formatul rămâne la fel.
  • Fiecare client urmărește alte coduri CPV, expresii, autorități și valori și are propriile excluderi.
  • Zero rezultate poate însemna o zi liniștită sau o preluare defectă. Sistemul trebuie să distingă cele două situații.
  • Fiecare rulare verifică și o perioadă deja parcursă, deci duplicatele și alertele repetate trebuie eliminate sigur.
  • Datele fiecărui client rămân separate, deși fluxul public este preluat o singură dată și apoi reutilizat.

Ce am livrat

Am construit întregul flux: preluare programată, filtrare, verificare, notificare și monitorizarea funcționării.

  • Client pentru API-ul SEAP, cu paginare, reîncercări și filtrare locală.
  • Scor de relevanță bazat pe coduri CPV, contextul titlului, autorități, valori și excluderi explicite.
  • Remindere pentru termene-limită, urmărirea eratelor și semnale timpurii din consultări, planuri și anunțuri de intenție.
  • Liste HTML disponibile offline, notificări prin email și Slack și un dashboard pentru stare, rulări și editarea profilurilor.
  • Istoricul rulărilor, detectarea anomaliilor, autentificare, roluri, migrări, backup și teste de regresie.

Arhitectură

O singură preluare, reguli pentru fiecare client

Preluare API public Paginare, reîncercare și perioade suprapuse
Decizie Potrivire cu profilul Scoruri deterministe și excluderi explicite
Operare Verificare + notificare Listă, etape, termene, email și Slack
Monitorizare Starea rulărilor Istoric, verificarea anomaliilor și alerte de eroare

Cum sunt prinse erorile silențioase

Un mesaj de dimineață trimis la timp poate ascunde o preluare incompletă. De aceea, Licto înregistrează fiecare rulare și o compară cu istoricul normal al profilului.

  • Sistemul separă cazul „zero anunțuri preluate” de cazul „zero anunțuri relevante”.
  • O scădere bruscă a numărului de anunțuri declanșează o alertă.
  • Dacă niciun anunț nu mai conține termen de depunere, sistemul semnalează o posibilă schimbare de structură a datelor.
  • Un timer separat detectează și cazul în care procesul zilnic nu pornește deloc.

Decizii importante

Folosirea datelor JSON
Portalul oferă deja date structurate. Parsarea paginilor HTML ar fi mai fragilă și nu ar aduce informații în plus.
Structura JSON trebuie totuși monitorizată, fiindcă nu este garantată ca API public de integrare.
Filtrare locală
Volumul săptămânal poate fi preluat integral. Așa nu depind de filtrele nedocumentate ale portalului și pot aplica reguli proprii.
Sursele care cer multe pagini de detaliu au nevoie de limite separate pentru numărul de solicitări.
Scor determinist
Fiecare rezultat arată codul CPV, expresia, autoritatea sau excluderea care i-a influențat scorul. Operatorul poate înțelege și regla filtrarea.
Profilurile trebuie actualizate de mână când se schimbă interesele clientului.
Suprapunere și deduplicare
Fiecare rulare se uită suficient de mult în urmă pentru a recupera datele după o eroare temporară. Cheile persistente împiedică dublarea anunțurilor și a reminderelor.
Baza de date și migrările devin piese critice.
Un reper pentru fiecare profil
Același prag zilnic nu funcționează în industrii diferite. Anomaliile sunt evaluate față de rulările reușite ale fiecărui profil.
La început, sistemul are nevoie de o perioadă de calibrare înainte să poată semnala abateri.

Ce poți verifica

Rezultate explicate Fiecare anunț păstrează motivele scorului și etapa curentă. Notificările, eratele și schimbările de termen sunt urmărite automat.
Control pentru operator Operatorul poate vedea starea, porni o actualizare și modifica regulile profilului fără acces la terminal.
Erori detectate automat Istoricul și verificările independente arată dacă o zi fără rezultate e normală sau e o preluare defectă.

Limite

Integrarea trebuie supravegheată.

Structura SEAP se poate schimba, unele surse cer multe solicitări, iar calitatea rezultatelor depinde de regulile fiecărui client. Pentru că sistemul este privat, acest case study prezintă doar arhitectura și deciziile tehnice, fără datele clienților.

Rol și tech stack

Am proiectat și construit întregul sistem: preluarea și filtrarea datelor, modelul de stare, interfața operatorului, notificările și detectarea erorilor.

Python · requests · profiluri YAML · SQLite · HTML generat · SMTP · Slack · systemd