fix: 预览按 draft-{id} 命名且重建全量同构 + C1 空台账改判数据待补 + 立项经费结余结论 + CLI 拆分 import-*/list-* + docx 占位黄底
This commit is contained in:
@@ -260,6 +260,7 @@ def cmd_add_project(
|
||||
program: str = "",
|
||||
start: str = "",
|
||||
end: str = "",
|
||||
approved_budget: str = "",
|
||||
expected_json: str = "",
|
||||
excerpt: str = "",
|
||||
status: str = "",
|
||||
@@ -278,7 +279,7 @@ def cmd_add_project(
|
||||
print(f"ERROR:ENTITLEMENT_DENIED {reason}")
|
||||
return 1
|
||||
fields: dict[str, Any] = {"project_no": project_no}
|
||||
for key, value in (("project_name", name), ("pi_name", pi), ("department", department), ("program", program), ("start_date", start), ("end_date", end), ("expected_json", expected_json), ("annual_report_excerpt", excerpt), ("status", status)):
|
||||
for key, value in (("project_name", name), ("pi_name", pi), ("department", department), ("program", program), ("start_date", start), ("end_date", end), ("approved_budget", approved_budget), ("expected_json", expected_json), ("annual_report_excerpt", excerpt), ("status", status)):
|
||||
if value:
|
||||
fields[key] = value
|
||||
payload = upsert_project(fields)
|
||||
@@ -411,6 +412,86 @@ def cmd_import(projects_json: str = "", achievements_json: str = "", expenses_js
|
||||
return 1
|
||||
|
||||
|
||||
def _cmd_import_one(label: str, raw_json: str, import_fn) -> int:
|
||||
"""单一台账批量导入(import-projects / import-achievements / import-expenses 共用)。"""
|
||||
log = _get_task_logger()
|
||||
with job_context(skill=SKILL_SLUG):
|
||||
log.info("task_start task_type=import_%s stage=ledger", label)
|
||||
emit(f"开始批量导入{label}", skill=SKILL_SLUG, stage="ledger")
|
||||
try:
|
||||
ok, reason = check_entitlement(SKILL_SLUG)
|
||||
if not ok:
|
||||
log.warning("entitlement_failed task_type=import_%s stage=auth", label)
|
||||
finish(status="failed", message=reason, skill=SKILL_SLUG, error_code="ENTITLEMENT_DENIED", stage="auth")
|
||||
print(f"ERROR:ENTITLEMENT_DENIED {reason}")
|
||||
return 1
|
||||
payload = import_fn(_parse_json_arg(raw_json, f"--{label}-json"))
|
||||
_print_json(payload)
|
||||
finish(status="success", message=f"导入完成:新增 {payload['created']},更新 {payload['updated']}", skill=SKILL_SLUG, stage="ledger")
|
||||
return 0
|
||||
except ValueError as exc:
|
||||
log.warning("task_failed task_type=import_%s error_code=PROJECT_INVALID detail=%s", label, exc)
|
||||
finish(status="failed", message=str(exc), skill=SKILL_SLUG, error_code="PROJECT_INVALID", stage="ledger")
|
||||
print(f"ERROR:PROJECT_INVALID {exc}")
|
||||
return 1
|
||||
except JobStopped:
|
||||
raise
|
||||
except Exception:
|
||||
log.exception("task_failed task_type=import_%s stage=ledger", label)
|
||||
finish(status="failed", message="批量导入异常,详见统一日志", skill=SKILL_SLUG, stage="ledger")
|
||||
return 1
|
||||
|
||||
|
||||
def cmd_import_projects(projects_json: str) -> int:
|
||||
from service.ledger_service import import_projects
|
||||
|
||||
return _cmd_import_one("projects", projects_json, import_projects)
|
||||
|
||||
|
||||
def cmd_import_achievements(achievements_json: str) -> int:
|
||||
from service.ledger_service import import_achievements
|
||||
|
||||
return _cmd_import_one("achievements", achievements_json, import_achievements)
|
||||
|
||||
|
||||
def cmd_import_expenses(expenses_json: str) -> int:
|
||||
from service.ledger_service import import_expenses
|
||||
|
||||
return _cmd_import_one("expenses", expenses_json, import_expenses)
|
||||
|
||||
|
||||
def _cmd_list_one(label: str, fetch) -> int:
|
||||
log = _get_task_logger()
|
||||
with job_context(skill=SKILL_SLUG):
|
||||
log.info("task_start task_type=list_%s", label)
|
||||
try:
|
||||
rows = fetch()
|
||||
_print_json({"ok": True, "count": len(rows), "rows": rows})
|
||||
return 0
|
||||
except Exception:
|
||||
log.exception("task_failed task_type=list_%s", label)
|
||||
print("ERROR:QUERY_FAILED 台账查询异常,详见统一日志")
|
||||
return 1
|
||||
|
||||
|
||||
def cmd_list_projects(status: str = "") -> int:
|
||||
from service.ledger_service import list_projects
|
||||
|
||||
return _cmd_list_one("projects", lambda: list_projects(status=status))
|
||||
|
||||
|
||||
def cmd_list_achievements(project_no: str) -> int:
|
||||
from service.ledger_service import list_achievements
|
||||
|
||||
return _cmd_list_one("achievements", lambda: list_achievements(project_no))
|
||||
|
||||
|
||||
def cmd_list_expenses(project_no: str) -> int:
|
||||
from service.ledger_service import list_expenses
|
||||
|
||||
return _cmd_list_one("expenses", lambda: list_expenses(project_no))
|
||||
|
||||
|
||||
def cmd_list(kind: str = "projects", project_no: str = "", status: str = "") -> int:
|
||||
log = _get_task_logger()
|
||||
from service.ledger_service import list_achievements, list_expenses, list_projects
|
||||
|
||||
Reference in New Issue
Block a user