diff --git a/app/modules/project/db.py b/app/modules/project/db.py index 00a4626..571e6c8 100644 --- a/app/modules/project/db.py +++ b/app/modules/project/db.py @@ -13,7 +13,7 @@ from __future__ import annotations import logging -from datetime import date, datetime +from datetime import date, datetime, time from typing import Any from psycopg.rows import dict_row @@ -331,12 +331,16 @@ class ProjectStore: priority: str = "normal", start_date: str | None = None, due_date: str | None = None, + start_time: str | None = None, + due_time: str | None = None, created_by: str = "", ) -> dict[str, Any]: ttl = store.validate_task_title(title) pr = store.validate_priority(priority) sd = store.validate_date(start_date) dd = store.validate_date(due_date) + sti = store.validate_time(start_time) + dti = store.validate_time(due_time) assignee = store.norm_str(assignee_email, lower=True) with self._pool.connection() as conn: with conn.transaction(): @@ -357,14 +361,15 @@ class ProjectStore: """ INSERT INTO tasks (project_id, stage_id, title, description, assignee_email, - assignee_name, priority, start_date, due_date, sort_order, created_by) - VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) + assignee_name, priority, start_date, due_date, + start_time, due_time, sort_order, created_by) + VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) RETURNING * """, ( project_id, stage_id, ttl, store.norm_str(description), assignee, store.norm_str(assignee_name), pr, sd, dd, - int(nxt["n"]), store.norm_str(created_by, lower=True), + sti, dti, int(nxt["n"]), store.norm_str(created_by, lower=True), ), ).fetchone() if assignee: @@ -406,6 +411,12 @@ class ProjectStore: if "due_date" in fields: sets.append("due_date = %s") params.append(store.validate_date(fields["due_date"])) + if "start_time" in fields: + sets.append("start_time = %s") + params.append(store.validate_time(fields["start_time"])) + if "due_time" in fields: + sets.append("due_time = %s") + params.append(store.validate_time(fields["due_time"])) if "assignee_email" in fields: new_assignee = store.norm_str(fields["assignee_email"], lower=True) sets.append("assignee_email = %s") @@ -714,6 +725,8 @@ class ProjectStore: for k, v in list(out.items()): if isinstance(v, datetime): out[k] = v.astimezone(KST).isoformat(timespec="seconds") + elif isinstance(v, time): + out[k] = v.strftime("%H:%M") elif isinstance(v, date): out[k] = v.isoformat() for k in ("id", "parent_id", "project_id", "stage_id", "task_id", "sort_order"): diff --git a/app/modules/project/router.py b/app/modules/project/router.py index 7712123..bff4c55 100644 --- a/app/modules/project/router.py +++ b/app/modules/project/router.py @@ -681,6 +681,8 @@ async def api_create_task( priority=payload.get("priority", "normal"), start_date=payload.get("start_date"), due_date=payload.get("due_date"), + start_time=payload.get("start_time"), + due_time=payload.get("due_time"), created_by=user["email"], ) except ValueError as exc: diff --git a/app/modules/project/store.py b/app/modules/project/store.py index 6495f39..ff398f4 100644 --- a/app/modules/project/store.py +++ b/app/modules/project/store.py @@ -108,6 +108,22 @@ def validate_date(d: Any) -> str | None: return v[:10] +def validate_time(t: Any) -> str | None: + """'HH:MM' 형식만 통과(초는 버림). 빈값/None 은 None(=종일).""" + v = norm_str(t) + if not v: + return None + parts = v.split(":") + try: + hh = int(parts[0]) + mm = int(parts[1]) if len(parts) > 1 else 0 + except (ValueError, IndexError): + raise ValueError(f"시간 형식이 올바르지 않습니다: {t}") + if not (0 <= hh <= 23 and 0 <= mm <= 59): + raise ValueError(f"시간 범위가 올바르지 않습니다: {t}") + return f"{hh:02d}:{mm:02d}" + + def build_subject_assigned(*, project_name: str, task_title: str, assignee: str) -> str: return f"[DBX 프로젝트] 업무 배정: {project_name} · {task_title} → {assignee}" diff --git a/app/modules/project/templates/project/inbox.html b/app/modules/project/templates/project/inbox.html index ffb35ed..e076dce 100644 --- a/app/modules/project/templates/project/inbox.html +++ b/app/modules/project/templates/project/inbox.html @@ -1,7 +1,7 @@ {% extends "erp_base.html" %} {% block head_extra %} - + {% endblock %} @@ -45,5 +45,5 @@ {% endif %} - + {% endblock %} diff --git a/app/modules/project/templates/project/index.html b/app/modules/project/templates/project/index.html index 4217a8f..e5010e6 100644 --- a/app/modules/project/templates/project/index.html +++ b/app/modules/project/templates/project/index.html @@ -1,7 +1,7 @@ {% extends "erp_base.html" %} {% block head_extra %} - + {% endblock %} @@ -100,5 +100,5 @@ - + {% endblock %} diff --git a/app/modules/project/templates/project/project.html b/app/modules/project/templates/project/project.html index cdc913a..b48b593 100644 --- a/app/modules/project/templates/project/project.html +++ b/app/modules/project/templates/project/project.html @@ -1,7 +1,7 @@ {% extends "erp_base.html" %} {% block head_extra %} - + @@ -222,6 +222,13 @@ + +