from decimal import Decimal from io import BytesIO import openpyxl from app.calc import selected_spread def test_selected_spread_in_cents(): months = selected_spread(Decimal("1000.00"), [1, 2, 3]) assert months[:3] == [Decimal("333.33"), Decimal("333.33"), Decimal("333.34")] assert sum(months) == Decimal("1000.00") and months[3:] == [0] * 9 assert selected_spread(Decimal("120"), [4, 1, 3, 2, 2]) == [30, 30, 30, 30] + [0] * 8 assert selected_spread(Decimal("12"), []) == [1] * 12 def _first_line(client, year_id): return client.get(f"/api/years/{year_id}").json()["categories"][0]["lines"][0] def test_line_split_over_chosen_months(client, imported): line = _first_line(client, imported) r = client.put(f"/api/lines/{line['id']}", json={"monthly_kind": "selected", "monthly_months": [4, 1, 2, 3, 3]}) assert r.status_code == 200, r.text after = _first_line(client, imported) assert after["monthly_kind"] == "selected" and after["monthly_months"] == [1, 2, 3, 4] assert after["adjusted"] == line["adjusted"] # the year total does not change, only when it is spent share = round(line["adjusted"] / 4, 2) assert after["months"][0] == share and after["months"][4:] == [0] * 8 assert round(sum(after["months"]), 2) == line["adjusted"] # the year's monthly totals follow; the monthly budget report shows the months year = client.get(f"/api/years/{imported}").json() assert year["costs"]["adjusted"] == client.get(f"/api/years/{imported}").json()["costs"]["adjusted"] assert client.get(f"/api/years/{imported}/reports/budget.xlsx").status_code == 200 assert client.put(f"/api/lines/{line['id']}", json={"monthly_kind": "selected", "monthly_months": []}).status_code == 400 assert client.put(f"/api/lines/{line['id']}", json={"monthly_months": [13]}).status_code == 400 # rolling over to next year keeps the chosen months nxt = client.post("/api/years", json={"year": 2028, "copy_from_id": imported}).json() copied = _first_line(client, nxt["id"]) assert copied["monthly_kind"] == "selected" and copied["monthly_months"] == [1, 2, 3, 4] # back to 12 months client.put(f"/api/lines/{line['id']}", json={"monthly_kind": "even", "monthly_months": None}) assert _first_line(client, imported)["months"][11] != 0 def test_template_keeps_chosen_months(client, imported): line = _first_line(client, imported) client.put(f"/api/lines/{line['id']}", json={"monthly_kind": "selected", "monthly_months": [1, 2, 3, 4, 7]}) dept = client.get("/api/departments").json()[0]["id"] r = client.get(f"/api/departments/{dept}/template.xlsx?lang=pt&from_year_id={imported}&year=2030") ws = openpyxl.load_workbook(BytesIO(r.content))["Linhas"] assert ws.cell(8, 23).value == "Dividir pelos meses" assert "1-4, 7" in [ws.cell(row, 23).value for row in range(9, 70)] # a hand-written month list on a row without typed months free = next(r for r in range(9, 70) if ws.cell(r, 2).value and ws.cell(r, 23).value is None and all(ws.cell(r, c).value is None for c in range(11, 23))) ws.cell(free, 23, "Set-Dez") buf = BytesIO() ws.parent.save(buf) res = client.post("/api/years/import", files={"file": ("t.xlsx", buf.getvalue())}, data={"department_id": str(dept)}).json() lines = [ln for c in client.get(f"/api/years/{res['year']['id']}").json()["categories"] for ln in c["lines"]] picked = [ln["monthly_months"] for ln in lines if ln["monthly_kind"] == "selected"] assert [1, 2, 3, 4, 7] in picked and [9, 10, 11, 12] in picked a = client.get(f"/api/years/{imported}").json()["costs"] b = client.get(f"/api/years/{res['year']['id']}").json()["costs"] assert abs(a["adjusted"] - b["adjusted"]) < 0.01