"""Отчёт по сотрудникам, трудоёмкость задач, возвраты нарядов, фильтры вкладки «Задачи».""" import os import tempfile from datetime import timedelta os.environ.setdefault("DATABASE_URL", os.environ.get("TEST_DATABASE_URL") or "sqlite:///" + os.path.join(tempfile.mkdtemp(), "pp.db").replace("\\", "/")) os.environ.setdefault("SCHEDULER_INTERVAL", "3600") os.environ.setdefault("SECRET_KEY", "test-secret-key-for-pytest-0123456789abcdef") os.environ.setdefault("DATA_DIR", tempfile.mkdtemp()) from fastapi.testclient import TestClient # noqa: E402 from app import config # noqa: E402 from app.main import app # noqa: E402 V1 = "/api/v1" PW = "Pass1234567" def test_people_report_and_work_filters(): with TestClient(app) as c: login = lambda u, p=PW: {"Authorization": "Bearer " + c.post(f"{V1}/auth/login", json={"username": u, "password": p}).json()["access_token"]} adm = login("admin", "admin") eng_pos = c.post(f"{V1}/positions", headers=adm, json={"name": "PP-Инженер", "kind": "engineer"}).json() dep = c.post(f"{V1}/departments", headers=adm, json={"name": "PP-Служба"}).json() a = c.post(f"{V1}/users", headers=adm, json={"username": "pp_a", "full_name": "Альфа Работник", "password": PW, "department_id": dep["id"]}).json() c.post(f"{V1}/users", headers=adm, json={"username": "pp_e", "full_name": "Инж Проверяющий", "password": PW, "position_id": eng_pos["id"]}) ta, te = login("pp_a"), login("pp_e") # задача с нормой трудоёмкости и задача без нормы (фактическое время) t1 = c.post(f"{V1}/tasks", headers=te, json={"title": "Норма 2.5 ч", "assignee_id": a["id"], "labor_hours": 2.5}).json() assert t1["labor_hours"] == 2.5 for s, cm in (("in_progress", ""), ("done", "ok")): c.post(f"{V1}/tasks/{t1['id']}/status", headers=ta, json={"status": s, "comment": cm}) t2 = c.post(f"{V1}/tasks", headers=te, json={"title": "Отменённая", "assignee_id": a["id"]}).json() c.post(f"{V1}/tasks/{t2['id']}/status", headers=ta, json={"status": "paused", "comment": "жду"}) c.post(f"{V1}/tasks/{t2['id']}/status", headers=ta, json={"status": "cancelled", "comment": "не нужно"}) # фильтры вкладки «Задачи»: поставленные мной mine_set = c.get(f"{V1}/tasks", headers=te, params={"created_by_me": True}).json() assert {x["title"] for x in mine_set} >= {"Норма 2.5 ч", "Отменённая"} # наряд: возврат с проверки и отклонение от нормы cl = c.post(f"{V1}/checklists", headers=adm, json={"name": "PP-чек", "items": [{"text": "Давление", "answer_type": "number", "min_value": 1, "max_value": 2}]}).json() o = c.post(f"{V1}/orders", headers=te, json={"title": "PP-наряд", "checklist_id": cl["id"], "assignee_user_id": a["id"], "reviewer_user_id": c.get(f"{V1}/me", headers=te).json()["id"]}).json() item = c.get(f"{V1}/orders/{o['id']}", headers=ta).json()["items"][0] c.put(f"{V1}/orders/{o['id']}/items/{item['id']}", headers=ta, json={"value": "5"}) st = c.post(f"{V1}/orders/{o['id']}/submit", headers=ta).json()["status"] if st == "review": assert c.post(f"{V1}/orders/{o['id']}/review", headers=te, json={"approve": False, "comment": "Переделать"}).status_code == 200 c.post(f"{V1}/orders/{o['id']}/submit", headers=ta) c.post(f"{V1}/orders/{o['id']}/review", headers=te, json={"approve": True}) now = config.now() q = {"from": (now - timedelta(days=1)).isoformat(), "to": (now + timedelta(days=1)).isoformat()} assert c.get(f"{V1}/reports/people", headers=ta, params=q).status_code == 403 rep = c.get(f"{V1}/reports/people", headers=te, params={**q, "department_id": dep["id"]}).json() assert [r["name"] for r in rep["rows"]] == ["Альфа Работник"] r = rep["rows"][0] assert r["tasks_done"] == 1 and r["tasks_cancelled"] == 1 and r["tasks_paused"] == 1 and r["orders_done"] == 1 assert r["deviations"] == 1 and r["hours"] >= 2.5 and r["on_time_pct"] is not None day = now.date().isoformat() assert r["calendar"][day]["n"] == 2 and r["calendar"][day]["h"] >= 2.5 assert len(rep["days"]) >= 2 pdf = c.get(f"{V1}/reports/people", headers=te, params={**q, "format": "pdf"}) assert pdf.status_code == 200 and pdf.content[:5] == b"%PDF-" csv = c.get(f"{V1}/reports/people", headers=te, params={**q, "format": "csv_calendar"}).content.decode("utf-8-sig") assert "Альфа Работник" in csv and "Итого ч" in csv # фильтры инцидентов для вкладки «Задачи» eq = c.post(f"{V1}/equipment", headers=adm, json={"name": "PP-Станок"}).json() c.post(f"{V1}/incidents", headers=ta, json={"equipment_id": eq["id"], "title": "PP-авария"}) assert [i["title"] for i in c.get(f"{V1}/incidents", headers=ta, params={"mine": True}).json()] == ["PP-авария"] assert c.get(f"{V1}/incidents", headers=ta, params={"q": "pp-стан"}).json()[0]["title"] == "PP-авария" assert all(i["source"] == "staff" for i in c.get(f"{V1}/incidents", headers=ta, params={"source": "staff"}).json())