PayrollManagementSystem/scripts/windows/README.md
liuwenxin 1461a8d113 feat(后端): 添加授权体系、系统监控与试用期计提
按 2026-11-02 需求补齐计划交付后端能力:
- 角色授权:权限目录化,接口统一准入校验,未登记默认拒绝;
  管理员判断改为按数据库角色重新判定,防止权限码持有者绕过
- 系统监控:单进程采集资源、请求与异常指标,分钟级聚合,
  阈值配置化;敏感配置增加 repr 保护,Redis 密码 URL 转义
- 试用期计提:按回款日判定并写入快照,年度结清与调整单联动;
  人员模型补试用期、离职日期与工资版本历史字段
- 计提模板:公式骨架受控,页面维护名称与参数绑定
- T+ 采集:自动化配置表与进度查询

内置角色禁停用保护对齐模块注释;核算规则版本提为常量并
补充批量核算失败堆栈日志。

影响范围:后端全部模块、数据库迁移 V22-V28
验证:uv run ruff check 通过;922 个单元测试全部通过;
集成测试因本机 MySQL 数据卷被其他容器锁定暂未运行
2026-11-03 11:20:55 +08:00

6.4 KiB
Raw Blame History

Windows 任务计划托管

本包托管后端、T+ worker 和每分钟周期检查。首次安装生成三个禁用任务并保留停止标记;自动周采集另外由应用配置启用。采集不会自动导入正式业务、核算或生成工资。

配置及账号准备

使用目标服务器已有受限服务账号,配置“作为批处理作业登录”、MySQL/Redis 连接和项目外的 T+ 只读连接文件。生产不能使用 SYSTEM。管理员须预先准备运行目录及文件权限:

  • 部署目录、Python 环境和全部程序文件,只允许管理员及指定服务账号维护,不允许普通 Users、Everyone、Authenticated Users 写入。
  • 只读连接文件和 backend/.env,仅限管理员、SYSTEM 与服务账号读取;连接文件不放进仓库。
  • 运行目录供服务账号写入日志、安装清单和停止标记,拒绝其他普通用户写入。上层目录也不能给普通用户删除/替换这些目录的权限。
  • 脚本安装前和 Start 前检查关键入口、文件所有者和上层目录 ACL;不会自动改变 ACL。管理员仍需确保部署树全部内容和 Python 依赖都受相同保护。
  • 安装清单保存服务账号 SID 和登录方式,Check/Start/Stop 均核验实际任务账号及 Limited 权限,发现漂移则拒绝操作。

应用需先完成经授权的迁移;当前 head 为 21f2a3b4c5d6(V20 调度状态、V21 状态默认值修正)。本次仅在隔离库验证,未迁移客户业务库。

backend/.env 中的非敏感开关:

T_PLUS_AUTOMATION_ENABLED=false
T_PLUS_SCHEDULE_WEEKDAY=0
T_PLUS_SCHEDULE_TIME=02:00

T_PLUS_AUTOMATION_ENABLED 只是未保存页面设置时的初始值。T+ 同步页保存开关后写入 tplus_automation_configs,维护程序以该源级设置为准;关闭页面开关会阻止后续自动排队,不影响当前任务和手动同步。

weekday 的 0~6 分别为周一至周日,时间固定按 Asia/Shanghai 解释。上线前保持自动化开关为 false。修改后重启托管进程,使后端与检查命令使用同一配置。

预检查和安装

在 Windows PowerShell 5 中执行,使用实际部署路径。以下为示例路径,不含真实凭据。

$project = 'D:\Payroll App'
$python = 'D:\Payroll App\backend\.venv\Scripts\python.exe'
$runtime = 'D:\Payroll Runtime'
$reader = 'D:\Payroll Secrets\reader.local.json'

# 只读预演:输出路径、动作、触发和恢复策略,不注册任务
& "$project\scripts\windows\Install-PayrollTasks.ps1" `
  -ProjectRoot $project -PythonPath $python -RuntimeDirectory $runtime -ConnectionFile $reader

# 检查脚本语法、任务策略、引号、ACL规则及账号核验;不注册任务
& "$project\scripts\windows\Test-PayrollTaskPlan.ps1" `
  -ProjectRoot $project -PythonPath $python -RuntimeDirectory $runtime -ConnectionFile $reader

客户环境安装需另行确认。确认后管理员才执行 Install-PayrollTasks.ps1 的同组参数,并增加 -ServiceAccount '域或主机\已有服务账号' -Apply。凭据通过交互框输入,不写入命令行、清单或日志。目录须提前准备且 ACL 合格,否则拒绝注册;已有同名任务/安装清单不会覆盖。安装过程部分失败时,已创建的任务仍保持禁用,按提示核对专用任务目录后处理。

测试模式只允许 \PayrollManagementSystem-Test-xxxxxxxx\(8 位十六进制)的独立目录及当前用户 Interactive/Limited 身份,同样要求显式 -Apply 和合格 ACL。不要用测试模式替代客户服务账号验收。

检查、启动、停用

# 检查状态、最近退出码、下次执行及任务身份/动作/恢复策略
& "$project\scripts\windows\Manage-PayrollTasks.ps1" -Action Check -RuntimeDirectory $runtime

# 预演启动或停用;增加 -Apply 才改变任务状态
& "$project\scripts\windows\Manage-PayrollTasks.ps1" -Action Start -RuntimeDirectory $runtime
& "$project\scripts\windows\Manage-PayrollTasks.ps1" -Action Stop -RuntimeDirectory $runtime

Start 的 -Apply 删除项目停止标记,启用并启动三项任务。Stop 的 -Apply 先写停止标记并禁用任务;worker 完成当前工作后退出,不再领取下一项。默认等待 30 秒,长查询未结束则返回 2,稍后 Check。仅在核实中断影响后,才使用 -Force -Apply 强制停止明确的项目任务;重启后遗留 RUNNING 批次标记中断,原数据及失败批次保留,由制作人核对后重试。

每项任务使用 IgnoreNew,异常退出间隔 1 分钟重启,最多 3 次;启动器保留子进程退出码。后端及 worker 开机触发,维护命令开机及每分钟触发,长任务无强制执行时限。启动器子进程隐藏运行,后端绑定 127.0.0.1,对外访问应沿用现有网关。

调度和异常处理

tplus-maintain --once 只排队最近已到期的一周,同周期幂等;停机后补一次,不逐周补积压。手动任务/正式导入工作区正在运行时延后排队。人工重试结果接入该周期,不会在人工恢复成功后再次重读原失败批次。

仅定时采集且错误均为明确断连或超时,才在终止后 5 分钟、15 分钟重试,最多两次。中途断连保留已暂存页并标记失败,重新全量读取由哈希去重。行级错误/部分失败、配置错误、字段错误、进程中断和正式导入不自动重试。原批次、重试关系与错误记录一直保留。

T+ 同步页显示自动化开关、心跳、最近成功和下次重试,以及失败/部分失败、排队超过 15 分钟、超过 8 天无成功、心跳中断提示。独立心跳每 30 秒写入,2 分钟无更新提示离线。日志按次写入 runtime\logs,不自动删除;不输出驱动连接文本。外部邮件及企业消息未启用。

验证范围

已验证 Windows PowerShell 5 的计划参数、单实例/重启设置、含空格路径、隐藏子进程、停止标记和退出码传递;测试未注册计划任务或连接业务数据库。应用侧已完成隔离库周期竞争、人工/自动重试竞争、上限及独立长查询心跳验证。

客户服务器实际注册、服务账号权限、开机触发、每分钟三次恢复和停止后不再启动,仍需在专用目标环境演练并留存 Check 输出。SQL Server 2008 R2 实机、备份全量/增量恢复链及生产启用分别验收,不由本机测试替代。