File size: 4,277 Bytes
b8e6434 54ad6b4 b8e6434 54ad6b4 b8e6434 54ad6b4 b8e6434 54ad6b4 b8e6434 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | from sqlalchemy.orm import Session
from datetime import datetime
from app.models.tender import TenderModel
from app.services.mercado_publico import fetch_tenders, get_tender_by_code
import json
async def sync_tenders_to_db(db: Session, keyword: str = None):
"""
Fetches tenders from API and saves/updates them in the database.
Fallback: Always injects demo software tenders.
"""
print(f"[Sync] Starting synchronization... keyword={keyword}")
# --- FALLBACK DEMO DATA ---
from datetime import datetime, timedelta
demo_tenders = [
{
"code": "2394-15-LR24",
"name": "Implementaci贸n Sistema ERP para Red de Salud Oriente",
"description": "Suministro, instalaci贸n y soporte de sistema de gesti贸n de recursos empresariales para red hospitalaria.",
"buyer": "Servicio de Salud Metropolitano",
"status": "Publicada",
"closing_date": datetime.now() + timedelta(days=20),
"estimated_amount": 450000000,
"region": "Metropolitana",
"sector": "Tecnolog铆a de la Informaci贸n",
"source": "Mercado P煤blico"
},
{
"code": "5021-10-LP24",
"name": "Plataforma de IA para An谩lisis de Datos Criminal铆sticos",
"description": "Desarrollo de algoritmos de visi贸n computacional y an谩lisis predictivo para seguridad ciudadana.",
"buyer": "Subsecretar铆a de Prevenci贸n del Delito",
"status": "Publicada",
"closing_date": datetime.now() + timedelta(days=12),
"estimated_amount": 180000000,
"region": "Metropolitana",
"sector": "Software & IA",
"source": "Mercado P煤blico"
}
]
for dt in demo_tenders:
exists = db.query(TenderModel).filter(TenderModel.code == dt["code"]).first()
if not exists:
db.add(TenderModel(**dt))
db.commit()
# --------------------------
try:
api_tenders = await fetch_tenders(keyword=keyword)
if not api_tenders:
print("[Sync] WARNING: API returned ZERO tenders. Fallback seeds used.")
return {"new": 2, "updated": 0, "message": "Demo data seeded"}
else:
print(f"[Sync] API returned {len(api_tenders)} tenders for processing.")
except Exception as e:
print(f"[Sync] API error (continuing with demo data): {e}")
return {"new": 2, "updated": 0, "message": "Demo data seeded (API Error)"}
count_new = 0
count_updated = 0
for api_t in api_tenders:
# Check if exists
db_tender = db.query(TenderModel).filter(TenderModel.code == api_t.code).first()
# Convert Pydantic model to dict for DB
tender_data = {
"code": api_t.code,
"name": api_t.name,
"buyer": api_t.buyer,
"status": api_t.status,
"closing_date": datetime.fromisoformat(api_t.closing_date.replace("Z", "")) if api_t.closing_date else None,
"description": api_t.description,
"estimated_amount": api_t.estimated_amount,
"source": api_t.source,
"region": api_t.region,
"sector": api_t.sector,
"items": [item.dict() for item in api_t.items] if api_t.items else [],
"attachments": [att.dict() for att in api_t.attachments] if api_t.attachments else []
}
if db_tender:
# Update existing
for key, value in tender_data.items():
setattr(db_tender, key, value)
count_updated += 1
else:
# Create new
new_tender = TenderModel(**tender_data)
db.add(new_tender)
count_new += 1
db.commit()
print(f"[Sync] Finished. New: {count_new}, Updated: {count_updated}")
return {"new": count_new, "updated": count_updated}
def clean_expired_tenders(db: Session):
"""
Removes tenders where closing_date is in the past.
"""
now = datetime.now()
expired = db.query(TenderModel).filter(TenderModel.closing_date < now).delete()
db.commit()
print(f"[Sync] Cleaned {expired} expired tenders.")
return expired
|