chore(pm): vendor the Aramesh/PM platform under pm/ (squash of Aramesh/PM @ 91f3271)
The PM panel (PmPanelPage -> iframe /pm/) needs the project-management platform served at /pm/ on the ERP domain. Source: org repo Aramesh/PM, branch feature/project-management-platform. Update via: git subtree pull --prefix=pm aramesh-pm feature/project-management-platform --squash
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import uuid
|
||||
from datetime import date
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from app.scheduling_service import calculate_schedule, check_for_cycle
|
||||
|
||||
|
||||
def test_cycle_detection():
|
||||
id_a = uuid.uuid4()
|
||||
id_b = uuid.uuid4()
|
||||
id_c = uuid.uuid4()
|
||||
|
||||
edges = [
|
||||
(id_a, id_b),
|
||||
(id_b, id_c),
|
||||
]
|
||||
|
||||
# Adding C -> A should detect cycle
|
||||
assert check_for_cycle(edges, id_c, id_a) is True
|
||||
|
||||
# Adding A -> A (self-loop) should detect cycle
|
||||
assert check_for_cycle(edges, id_a, id_a) is True
|
||||
|
||||
# Adding C -> D (new node) should not detect cycle
|
||||
id_d = uuid.uuid4()
|
||||
assert check_for_cycle(edges, id_c, id_d) is False
|
||||
|
||||
|
||||
def test_cpm_forward_and_backward_pass():
|
||||
id_a = uuid.uuid4()
|
||||
id_b = uuid.uuid4()
|
||||
id_c = uuid.uuid4()
|
||||
|
||||
t_a = SimpleNamespace(id=id_a, duration=3, planned_start=date(2026, 1, 1), parent_id=None, progress=0)
|
||||
t_b = SimpleNamespace(id=id_b, duration=4, planned_start=None, parent_id=None, progress=0)
|
||||
t_c = SimpleNamespace(id=id_c, duration=2, planned_start=None, parent_id=None, progress=0)
|
||||
|
||||
# A (3d) -[FS + 1 lag]-> B (4d) -[FS + 0 lag]-> C (2d)
|
||||
rel_ab = SimpleNamespace(from_task_id=id_a, to_task_id=id_b, relation_type="FS", lag_days=1)
|
||||
rel_bc = SimpleNamespace(from_task_id=id_b, to_task_id=id_c, relation_type="FS", lag_days=0)
|
||||
|
||||
res = calculate_schedule([t_a, t_b, t_c], [rel_ab, rel_bc], project_start=date(2026, 1, 1))
|
||||
|
||||
sched = res["tasks_schedule"]
|
||||
|
||||
# Task A: 2026-01-01, duration 3 is a gap -> ends 2026-01-04
|
||||
assert sched[id_a]["planned_start"] == date(2026, 1, 1)
|
||||
assert sched[id_a]["planned_end"] == date(2026, 1, 4)
|
||||
|
||||
# Task B starts right after A finishes (Jan 4) plus 1 lag day = Jan 5
|
||||
assert sched[id_b]["planned_start"] == date(2026, 1, 5)
|
||||
# B: duration 4 gap -> Jan 5 + 4 = Jan 9
|
||||
assert sched[id_b]["planned_end"] == date(2026, 1, 9)
|
||||
|
||||
# Task C starts Jan 9, duration 2 gap -> ends Jan 11
|
||||
assert sched[id_c]["planned_start"] == date(2026, 1, 9)
|
||||
assert sched[id_c]["planned_end"] == date(2026, 1, 11)
|
||||
|
||||
# All three are on critical path
|
||||
assert id_a in res["critical_path"]
|
||||
assert id_b in res["critical_path"]
|
||||
assert id_c in res["critical_path"]
|
||||
Reference in New Issue
Block a user