Files
chenfuqiang ee2a4d9e22
All checks were successful
技能自动化发布 / release (push) Successful in 15s
feat: 初始化高校人事请假考勤技能 (process-leave-attendance-default)
基于 skill-template 脚手架开发,包含:
- 5 张业务表(教职工、请假政策、考勤日历、请假记录、假期余额)
- 请假核算引擎(扣薪计算、审批层级判定、年假抵扣)
- CLI 入口(import-employees / calculate-leave / render-html)
- HTML 审批与扣薪报告生成
- 示例数据与完整测试套件(295 tests passed)
2026-09-07 16:59:24 +08:00

138 lines
4.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""CLI:高校人事请假考勤命令分发。"""
from __future__ import annotations
import argparse
import sys
from typing import List, Optional
from service.task_service import (
cmd_calculate_leave,
cmd_config_path,
cmd_health,
cmd_import_employees,
cmd_init_db,
cmd_render_html,
cmd_run,
cmd_version,
)
from util.argparse_zh import ZhArgumentParser
from util.config_bootstrap import bootstrap_skill_config
from util.constants import LOG_LOGGER_NAME, SKILL_SLUG
from util.logging_config import get_skill_logger, setup_skill_logging
def _cli_str_or_none(raw: Optional[str]) -> Optional[str]:
if raw is None:
return None
v = str(raw).strip()
return v or None
def _handle_run(args: argparse.Namespace) -> int:
tail = [str(x).strip() for x in (args.run_tail or []) if str(x).strip()]
if len(tail) > 2:
print("参数过多。")
print("用法:python main.py run [target [input_id]] | run [-t target] [-i input_id]")
return 1
t_target: Optional[str] = None
t_input: Optional[str] = None
if len(tail) == 2:
t_target, t_input = tail[0], tail[1]
elif len(tail) == 1:
if tail[0].isdigit():
t_input = tail[0]
else:
t_target = tail[0]
pick_t = _cli_str_or_none(getattr(args, "target", None))
pick_i = _cli_str_or_none(getattr(args, "input_id", None))
target = pick_t or t_target
input_id = pick_i or t_input
return cmd_run(target=target, input_id=input_id)
def build_parser() -> ZhArgumentParser:
p = ZhArgumentParser(
prog="main.py",
description="高校人事请假考勤:导入教职工、请假核算、审批与扣薪报告。",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
sub = p.add_subparsers(dest="cmd", required=True, parser_class=ZhArgumentParser)
sp = sub.add_parser("run", help="兼容入口(需 calculate-leave 子命令)")
sp.add_argument("--target", "-t", default=None, metavar="教职工id")
sp.add_argument("--input-id", "-i", default=None, metavar="教职工id", dest="input_id")
sp.add_argument("run_tail", nargs="*", metavar="位置参数")
sp.set_defaults(handler=_handle_run)
sp = sub.add_parser("import-employees", help="从输入目录导入教职工 JSON")
sp.add_argument("--file", "-f", default=None, metavar="JSON文件")
sp.set_defaults(handler=lambda a: cmd_import_employees(file_path=a.file))
sp = sub.add_parser("calculate-leave", help="核算请假扣薪与审批层级")
sp.add_argument("--employee-id", "-e", required=True, dest="employee_id")
sp.add_argument("--leave-type", required=True, dest="leave_type")
sp.add_argument("--start-date", required=True, dest="start_date")
sp.add_argument("--end-date", required=True, dest="end_date")
sp.add_argument("--has-certificate", default=None, dest="has_certificate")
sp.add_argument("--certificate-type", default=None, dest="certificate_type")
sp.set_defaults(
handler=lambda a: cmd_calculate_leave(
employee_id=a.employee_id,
leave_type=a.leave_type,
start_date=a.start_date,
end_date=a.end_date,
has_certificate=a.has_certificate,
certificate_type=a.certificate_type,
)
)
sp = sub.add_parser("render-html", help="生成请假审批与扣薪 HTML 报告")
sp.add_argument("--request-id", "-r", default=None, dest="request_id")
sp.set_defaults(handler=lambda a: cmd_render_html(request_id=a.request_id))
sp = sub.add_parser("health", help="健康检查")
sp.set_defaults(handler=lambda _a: cmd_health())
sp = sub.add_parser("config-path", help="输出配置与数据路径")
sp.set_defaults(handler=lambda _a: cmd_config_path())
sp = sub.add_parser("version", help="版本信息")
sp.set_defaults(handler=lambda _a: cmd_version())
sp = sub.add_parser("init-db", help="初始化数据库并同步示例数据")
sp.set_defaults(handler=lambda _a: cmd_init_db())
return p
def main(argv: Optional[List[str]] = None) -> int:
argv = argv if argv is not None else sys.argv[1:]
bootstrap_skill_config()
setup_skill_logging(SKILL_SLUG, LOG_LOGGER_NAME)
get_skill_logger().info("cli_start argv=%s", sys.argv)
if not argv:
print(
"高校人事请假考勤 — 用法:python main.py import-employees | calculate-leave | "
"render-html | health | version | init-db"
)
return 1
short = {
"run",
"import-employees",
"calculate-leave",
"render-html",
"health",
"config-path",
"version",
"init-db",
"-h",
"--help",
}
if len(argv) == 2 and argv[0] not in short:
return cmd_run(target=argv[0], input_id=argv[1])
parser = build_parser()
args = parser.parse_args(argv)
return int(args.handler(args))