PayrollManagementSystem/scripts/windows/Manage-PayrollTasks.ps1
liuwenxin 108bf87225 feat(核算)!: 添加 T+ 正式核算与采集托管
补齐源快照、资料预演、正式导入及工资核算的依赖链路。
新增版本化输入、逐段 FIFO、生成锁和结构化当月调整,
并提供默认关闭的周期采集、有限重试及 Windows 托管。

原始客户资料、私有配置及首页改动不纳入本次提交。

BREAKING CHANGE: 升级前需应用新增迁移,并通过
PAYROLL_MAKER_USER_ID 绑定实际工资制作人,否则业务只读。
旧单批次核算默认关闭;历史兼容需显式启用
PAYROLL_ALLOW_LEGACY_CALCULATION。生产启用和真实金额待验收。
2026-11-02 09:42:53 +08:00

64 lines
4.1 KiB
PowerShell
Raw 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.

[CmdletBinding(SupportsShouldProcess = $true)]
param(
[Parameter(Mandatory = $true)][ValidateSet('Check', 'Start', 'Stop')][string]$Action,
[Parameter(Mandatory = $true)][string]$RuntimeDirectory,
[switch]$Apply,
[switch]$Force,
[ValidateRange(0, 600)][int]$GraceSeconds = 30
)
. (Join-Path $PSScriptRoot 'TaskHost.Common.ps1')
$runtime = [IO.Path]::GetFullPath($RuntimeDirectory)
$manifest = Join-Path $runtime 'task-manifest.json'
if (-not (Test-Path -LiteralPath $manifest -PathType Leaf)) { throw '未找到项目安装清单,拒绝管理其他任务。' }
$saved = Get-Content -LiteralPath $manifest -Raw | ConvertFrom-Json
if (-not $saved.PSObject.Properties['ServiceSid'] -or -not $saved.PSObject.Properties['LogonType']) {
throw '安装清单缺少账号核验信息,请管理员核对后重新准备安装。'
}
$plan = Get-PayrollTaskPlan -ProjectRoot $saved.ProjectRoot -PythonPath $saved.PythonPath -RuntimeDirectory $runtime `
-ConnectionFile $saved.ConnectionFile -TaskPath $saved.TaskPath -ApiPort $saved.ApiPort
$tasks = foreach ($expected in $plan.Tasks) {
$actual = Get-ScheduledTask -TaskPath $plan.TaskPath -TaskName $expected.Name -ErrorAction Stop
Assert-PayrollTaskPrincipal -Actual $actual.Principal -Expected $saved
if (@($actual.Actions).Count -ne 1 -or $actual.Actions[0].Execute -ne $expected.Execute -or
$actual.Actions[0].Arguments -ne $expected.Arguments -or $actual.Actions[0].WorkingDirectory -ne $expected.WorkingDirectory) {
throw '任务动作与项目清单不一致,拒绝启动或停止。'
}
$info = Get-ScheduledTaskInfo -TaskPath $plan.TaskPath -TaskName $expected.Name
[pscustomobject]@{ Name = $expected.Name; State = [string]$actual.State;
LastTaskResult = $info.LastTaskResult; LastRunTime = $info.LastRunTime; NextRunTime = $info.NextRunTime;
SettingsValid = ($actual.Settings.MultipleInstances -eq 'IgnoreNew' -and $actual.Settings.RestartCount -eq 3 -and
$actual.Settings.RestartInterval -eq 'PT1M' -and $actual.Settings.ExecutionTimeLimit -eq 'PT0S') }
}
if ($Action -eq 'Check') {
[pscustomobject]@{ TaskPath = $plan.TaskPath; StopRequested = (Test-Path -LiteralPath $plan.StopFile); Tasks = @($tasks) } | ConvertTo-Json -Depth 4
if (@($tasks | Where-Object { -not $_.SettingsValid }).Count) { exit 1 }
exit 0
}
if (-not $Apply -or -not $PSCmdlet.ShouldProcess($plan.TaskPath, $Action)) {
[pscustomobject]@{ Preview = $true; Action = $Action; TaskPath = $plan.TaskPath; Names = @($tasks.Name) } | ConvertTo-Json
return
}
if (@($tasks | Where-Object { -not $_.SettingsValid }).Count) { throw '任务恢复设置不符合交付约定,拒绝改变运行状态。' }
if ($Action -eq 'Start') {
Assert-PayrollHostAccess -Plan $plan -ServiceSid $saved.ServiceSid
if (Test-Path -LiteralPath $plan.StopFile) { Remove-Item -LiteralPath $plan.StopFile }
foreach ($task in $tasks) { Enable-ScheduledTask -TaskPath $plan.TaskPath -TaskName $task.Name | Out-Null; Start-ScheduledTask -TaskPath $plan.TaskPath -TaskName $task.Name }
Write-Output '托管任务已启动;是否自动排队仍由T_PLUS_AUTOMATION_ENABLED决定。'
} else {
'运维请求停止领取任务' | Set-Content -LiteralPath $plan.StopFile -Encoding UTF8
foreach ($task in $tasks) { Disable-ScheduledTask -TaskPath $plan.TaskPath -TaskName $task.Name | Out-Null }
$deadline = (Get-Date).AddSeconds($GraceSeconds)
do {
$running = @($tasks | Where-Object { (Get-ScheduledTask -TaskPath $plan.TaskPath -TaskName $_.Name).State -eq 'Running' })
if (-not $running.Count) { break }
Start-Sleep -Seconds 1
} while ((Get-Date) -lt $deadline)
if ($running.Count -and $Force) {
foreach ($task in $running) { Stop-ScheduledTask -TaskPath $plan.TaskPath -TaskName $task.Name }
Write-Output '已强制停止明确的项目任务;未结束的采集需在重启后人工核对中断记录。'
} elseif ($running.Count) {
Write-Output '已停止领取新任务,现有长采集尚在退出;未强制终止,可稍后Check。'
exit 2
} else { Write-Output '项目托管任务已停止。' }
}