103 lines
6.8 KiB
Markdown
103 lines
6.8 KiB
Markdown
# PM API Contract (v3) — Standalone Native Platform — پایه: /api/v1
|
||
|
||
پلتفرم مدیریت پروژه ساختمانی بومی (Standalone)، مستقل و بدون وابستگی به هیچ سیستم خارجی.
|
||
|
||
## Auth
|
||
- `POST /auth/login` `{username, password}` → `{data:{token, user:{id, username, display_name, role}}}`
|
||
- `GET /auth/dev-roles` (در حالت توسعه) → لیست نقشهای آماده جهت ورود سریع
|
||
- `POST /auth/dev-login` `{role}` (در حالت توسعه) → دریافت سریع توکن نقش انتخابی
|
||
- همه endpointها (جز لاگین و فایلهای عمومی) هدر `Authorization: Bearer <token>` میخواهند.
|
||
- خطاها: `{"error": {"code", "message", "field"?}}` — کدها: `VALIDATION_ERROR` (400)،
|
||
`UNAUTHORIZED` (401)، `FORBIDDEN` (403)، `NOT_FOUND` (404)، `CONFLICT` (409)،
|
||
`UPSTREAM_UNAVAILABLE` (503).
|
||
|
||
## تاریخ جلالی
|
||
- **همه تاریخهای قابل مشاهده در UI شمسیاند.** API هم ISO میپذیرد/میدهد و هم شمسی.
|
||
- هر تسک علاوه بر `start_date`/`due_date` (ISO) فیلدهای `start_date_jalali`/
|
||
`due_date_jalali` را هم برمیگرداند («1405/06/23»).
|
||
- `PATCH /tasks/{id}/dates` هر دو قالب را میپذیرد: `1405/06/23` یا `2026-09-14`
|
||
(سال ≥ 1700 میلادی، کمتر از آن شمسی تفسیر میشود). روز نامعتبر → 400.
|
||
- تبدیلها در `backend/app/utils/jalali.py` و `frontend/src/lib/jalali.ts` انجام میشوند.
|
||
|
||
## Dashboard
|
||
- `GET /dashboard/today` → `{data:{summary:{problems,warnings,ok}, sections:{overdue,due_today,awaiting_qc,failed_qc,blocked,upcoming}}}`
|
||
- `awaiting_qc` = وضعیتهای `pre_qc_pending|exec_qc_pending|ready`
|
||
- `failed_qc` = وضعیتهای `pre_qc_failed|qc_failed_rework`
|
||
|
||
## Projects
|
||
- `GET /projects` → `[...{id, name, identifier, description, active, erp_project_id, created_at, stats:{total, awaiting_qc, failed_qc, overdue}}]`
|
||
- `POST /projects` → ساخت پروژه جدید
|
||
- `GET /projects/{id}` → جزئیات پروژه به همراه آمارهای تسکها
|
||
- `PUT /projects/{id}` | `DELETE /projects/{id}`
|
||
- `GET /projects/{id}/gantt` → دادههای گانت چارت پروژه
|
||
- `PATCH /projects/{id}/erp-mapping {erp_project_id}`
|
||
|
||
## Tasks
|
||
- `GET /tasks?project_id=&search=&qc_status=&status=&page=&page_size=`
|
||
- `POST /tasks` → ثبت فعالیت/تسک جدید
|
||
- `GET /tasks/{id}` → تسک + `relations` + `children` + **`qc`** + **`qc_definitions`** + `defects` + `open_defects`
|
||
- `PUT /tasks/{id}` → ویرایش اطلاعات تسک
|
||
- `DELETE /tasks/{id}` → حذف تسک
|
||
- `PATCH /tasks/{id}/progress {percentage: 0..100}`
|
||
- **قاعده ۱:** اگر `percentage > 0` و بازرسی پیش از اجرا تأیید نشده باشد → 400
|
||
«بازرسی پیش از اجرا تأیید نشده است (N سؤال باقیمانده)»
|
||
- **قاعده ۲:** اگر `percentage >= 100` و هر سؤال الزامی تأییدنشده/مردود باشد → 400
|
||
«تا زمانی که همه بازرسیهای الزامی تأیید نشوند پیشرفت ۱۰۰٪ مجاز نیست (…)»
|
||
- `PATCH /tasks/{id}/dates {start_date?, due_date?}` (ISO یا شمسی)
|
||
- `POST /tasks/relations` | `DELETE /tasks/relations/{id}` → مدیریت روابط وابستگی تسکها (FS, SS, FF, SF)
|
||
|
||
### شکل بلوک `qc` در جزئیات تسک
|
||
```json
|
||
{"pre": {"total":3,"passed":3,"failed":0,"pending":0,"na":0,"required_unresolved":0,"status":"passed"},
|
||
"exec": {"total":6,"passed":2,"failed":1,"pending":3,"na":0,"required_unresolved":4,"status":"pending"},
|
||
"all": { /* مجموع */ },
|
||
"status": "exec_qc_pending",
|
||
"can_start": true, "can_complete": false,
|
||
"block_reasons": ["تا زمانی که همه بازرسیهای الزامی تأیید نشوند پیشرفت ۱۰۰٪ مجاز نیست (۴ سؤال باقیمانده، ۱ مورد مردود)"]}
|
||
```
|
||
|
||
### وضعیتهای `qc_status` روی تسک
|
||
`none` · `pre_qc_pending` · `pre_qc_failed` · `ready` · `exec_qc_pending` ·
|
||
`in_progress` · `qc_failed_rework` · `final_passed`
|
||
|
||
## QC — تعریف (Definition)
|
||
### قالبهای سراسری (قابل استفاده مجدد)
|
||
- `GET /qc/templates` → `[{id,name,activity_type,description,questions:[{id,phase,text,sort_order,required}]}]`
|
||
- `POST /qc/templates {name, activity_type?, description?, questions?:[…]}` → `{data:{id}}`
|
||
- `PATCH /qc/templates/{id} {name?,activity_type?,description?}`
|
||
- `DELETE /qc/templates/{id}`
|
||
- `POST /qc/templates/{id}/questions {phase,text,required?,sort_order?}`
|
||
- `PATCH /qc/questions/{qid} {text?,phase?,required?,sort_order?}`
|
||
- `DELETE /qc/questions/{qid}`
|
||
- `PUT /qc/templates/{id}/questions {questions:[…]}` — جایگزینی گروهی (برای ادیتور)
|
||
|
||
`phase` ∈ `"pre"` (پیش از اجرا) · `"during"` (هنگام اجرا) · `"after"` (پس از اجرا)
|
||
|
||
### تعریف مخصوص تسک (کپی مستقل — ویرایش آن قالب سراسری را تغییر نمیدهد)
|
||
- `GET /qc/tasks/{task_id}` → `{data:{task, definitions:[{id,name,source_template_id,created_at,questions:[{…,result,history_count}],summary}], readiness}}`
|
||
- `POST /qc/tasks/{task_id}/definition {name?, template_id?}` → **کپی عمیق** سؤالات قالب
|
||
- `PATCH /qc/definitions/{id} {name}` | `DELETE /qc/definitions/{id}`
|
||
- `POST /qc/definitions/{id}/questions {text,phase,required?,sort_order?}`
|
||
- `PATCH /qc/task-questions/{qid} {text?,phase?,required?,sort_order?}`
|
||
- `DELETE /qc/task-questions/{qid}`
|
||
|
||
## QC — اجرا (Execution)
|
||
- `PUT /qc/task-questions/{qid}/result {answer:"pass"|"fail"|"na", comment?}`
|
||
→ `{data:{question_id, answer, task_qc_status, readiness}}`
|
||
- پاسخها **append-only** هستند (تاریخچه میماند؛ بازرسی مجدد پس از رفع عیب ممکن است)
|
||
- تعریف و اجرا کاملاً جدا هستند: هنگام ساخت/کپی سؤال هیچ پاس/ردی ثبت نمیشود.
|
||
- عیبها:
|
||
- `POST /qc/defects {task_id, question_id?, title, description?, severity?, corrective_action?, photo_id?}`
|
||
- `POST /qc/defects/{id}/resolve {resolution_notes?}`
|
||
- عکس عیب: `POST /files` (multipart) → `{data:{id, url}}` سپس `photo_id`
|
||
|
||
## فایلها
|
||
- `POST /files` multipart (jpg/png/webp تا ۱۰MB) → `{data:{id,url,filename}}`
|
||
- `GET /files/{id}`
|
||
|
||
## Materials / Resources (یکپارچگی ERP)
|
||
- `GET/POST /tasks/{task_id}/materials` · `PATCH/DELETE /materials/{req_id}`
|
||
- `GET /erp/materials?search=` · `GET /erp/projects`
|
||
- `POST /materials/{req_id}/reserve|purchase-request` · `GET /reservations` · `POST /reservations/{id}/release`
|
||
- `GET/PATCH /purchase-requests` · `POST /projects/{project_id}/erp-mapping`
|