admin / Apex
publicBid Management and Orchestration Tool with AI Capability
Apex / Synapse-Apexv2 / backend / app / services / scheduling.py
1733 B · main
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 | """Bid plan back-scheduling from the submission date (Module 2 step 3).""" from __future__ import annotations from datetime import date, timedelta def sub_working_days(end: date, working_days: int) -> date: """Return the date `working_days` business days before `end`.""" d = end remaining = working_days while remaining > 0: d -= timedelta(days=1) if d.weekday() < 5: # Mon-Fri remaining -= 1 return d def build_plan(start_date: date, submission_date: date, milestones: list[dict], requirements: list[dict]) -> list[dict]: """Return plan task dicts (milestones + one task per requirement).""" tasks: list[dict] = [] for m in milestones: if m.get("from") == "start": due = start_date else: due = sub_working_days(submission_date, int(m.get("offset_working_days_before_submission", 0))) tasks.append({ "name": m["name"], "kind": "milestone", "requirement_id": None, "due": due.isoformat(), "start": due.isoformat(), "status": "pending", }) # requirement tasks: spread between "requirement review complete" window and # "first drafts complete" milestone, defaulting to submission - 12 wd. draft_due = sub_working_days(submission_date, 12) for req in requirements: tasks.append({ "name": f"Respond to {req.get('ref') or 'requirement'}", "kind": "task", "requirement_id": req.get("id"), "due": draft_due.isoformat(), "start": start_date.isoformat(), "status": "pending", "planned_hours": 4, }) return tasks |