Catalyst / admin/Apex 14.8 GB / 57.8 GB 40.0 GB free
Help Sign in

admin / Apex

public

Bid Management and Orchestration Tool with AI Capability

Code Issues Pull requests Pipelines Packages Security Insights Wiki Settings
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