收口接单大厅模板价格同步与本地开发容器

This commit is contained in:
yml
2026-11-14 21:36:36 +08:00
parent b03599eca7
commit 9a7aaf605e
26 changed files with 1180 additions and 344 deletions
@@ -0,0 +1,171 @@
import { closeDb, query } from '../src/db/client.js'
import type { WorkOrderRow, WorkProductRuleRow } from '../src/repositories/worker-platform/types.js'
import { resolveWorkOrderTemplatePriceProjection } from '../src/services/worker-platform/work-order-hall-pricing-service.js'
type ShareAggregate = {
work_order_id: number
joined_quantity: number
locked_share_reward: number
}
type AuditIssue = {
severity: 'critical' | 'warning'
code: string
workOrderId: number
status: string
detail: string
}
const rows = await query<WorkOrderRow>(
`SELECT *
FROM work_orders
WHERE product_rule_id IS NOT NULL
AND assigned_worker_id IS NULL
AND status IN ('pending_material', 'unassigned', 'open')
AND NOT (COALESCE(material_json, '{}'::jsonb) ? 'consignment')
ORDER BY id`,
)
const workOrders = rows.rows
const ruleIds = [...new Set(workOrders.map((row) => Number(row.product_rule_id || 0)))]
const workOrderIds = workOrders.map((row) => Number(row.id))
const rulesResult =
ruleIds.length > 0
? await query<WorkProductRuleRow>(
'SELECT * FROM work_product_rules WHERE id = ANY($1::bigint[])',
[ruleIds],
)
: { rows: [] as WorkProductRuleRow[] }
const versionsResult =
ruleIds.length > 0
? await query<{ work_product_rule_id: number; id: number }>(
`SELECT DISTINCT ON (work_product_rule_id)
work_product_rule_id, id
FROM cost_versions
WHERE work_product_rule_id = ANY($1::bigint[])
AND status = 'active'
AND effective_from <= NOW()
AND (effective_to IS NULL OR effective_to > NOW())
ORDER BY work_product_rule_id, effective_from DESC, id DESC`,
[ruleIds],
)
: { rows: [] as Array<{ work_product_rule_id: number; id: number }> }
const sharesResult =
workOrderIds.length > 0
? await query<ShareAggregate>(
`SELECT
work_order_id,
COALESCE(SUM(quantity), 0)::int AS joined_quantity,
COALESCE(SUM(share_reward), 0)::bigint AS locked_share_reward
FROM work_order_shares
WHERE work_order_id = ANY($1::bigint[])
AND status != 'cancelled'
GROUP BY work_order_id`,
[workOrderIds],
)
: { rows: [] as ShareAggregate[] }
const rules = new Map(rulesResult.rows.map((rule) => [Number(rule.id), rule]))
const activeVersions = new Map(
versionsResult.rows.map((version) => [Number(version.work_product_rule_id), Number(version.id)]),
)
const shareAggregates = new Map(
sharesResult.rows.map((share) => [Number(share.work_order_id), share]),
)
const issues: AuditIssue[] = []
for (const workOrder of workOrders) {
const ruleId = Number(workOrder.product_rule_id || 0)
const rule = rules.get(ruleId)
const activeVersionId = activeVersions.get(ruleId) || 0
const share = shareAggregates.get(Number(workOrder.id))
const joinedQuantity = Number(share?.joined_quantity || 0)
const lockedShareReward = Number(share?.locked_share_reward || 0)
const severity = workOrder.status === 'open' ? 'critical' : 'warning'
if (!rule) {
issues.push({
severity,
code: 'template_missing',
workOrderId: Number(workOrder.id),
status: workOrder.status,
detail: `product_rule_id=${ruleId} 不存在`,
})
continue
}
if (!activeVersionId) {
issues.push({
severity,
code: 'active_cost_version_missing',
workOrderId: Number(workOrder.id),
status: workOrder.status,
detail: `模板 ${ruleId} 没有当前生效成本版本`,
})
continue
}
if (Number(workOrder.hall_price_version_id || 0) !== activeVersionId) {
issues.push({
severity,
code: 'hall_price_version_stale',
workOrderId: Number(workOrder.id),
status: workOrder.status,
detail: `当前=${Number(workOrder.hall_price_version_id || 0) || 'NULL'} 应=${activeVersionId}`,
})
}
const projection = resolveWorkOrderTemplatePriceProjection({ rule, workOrder })
if (!projection) {
issues.push({
severity,
code: 'template_price_invalid',
workOrderId: Number(workOrder.id),
status: workOrder.status,
detail: '模板当前配置无法计算工单价格',
})
continue
}
const totalQuantity = Math.max(1, Number(workOrder.sharing_total_quantity || 1))
const expectedReward = workOrder.sharing_enabled
? lockedShareReward +
Math.max(0, totalQuantity - joinedQuantity) * Number(projection.sharingUnitReward || 0)
: projection.rewardAmount
if (Number(workOrder.reward_amount || 0) !== expectedReward) {
issues.push({
severity,
code: 'reward_amount_stale',
workOrderId: Number(workOrder.id),
status: workOrder.status,
detail: `当前=${Number(workOrder.reward_amount || 0)} 应=${expectedReward}`,
})
}
if (
workOrder.sharing_enabled &&
Number(workOrder.sharing_unit_reward || 0) !== Number(projection.sharingUnitReward || 0)
) {
issues.push({
severity,
code: 'sharing_unit_reward_stale',
workOrderId: Number(workOrder.id),
status: workOrder.status,
detail: `当前=${Number(workOrder.sharing_unit_reward || 0)} 应=${Number(projection.sharingUnitReward || 0)}`,
})
}
}
const critical = issues.filter((issue) => issue.severity === 'critical')
const warnings = issues.filter((issue) => issue.severity === 'warning')
console.log(
JSON.stringify(
{
ok: critical.length === 0,
checkedAt: new Date().toISOString(),
scannedWorkOrders: workOrders.length,
critical,
warnings,
},
null,
2,
),
)
await closeDb()
if (critical.length > 0) process.exitCode = 1