fix: align signature review and admin operations

This commit is contained in:
hectorzhao
2026-07-27 22:07:51 +08:00
parent 9891ffee23
commit df70b336a0
22 changed files with 326 additions and 57 deletions
@@ -90,21 +90,24 @@ export class ReviewGovernanceService {
});
if (!item) throw new NotFoundException('Signature not found');
const payload = asRecord(item.drainageInfo);
const profile = asRecord(payload.signatureProfile);
const missing: string[] = [];
if (!item.applicationId) missing.push('未绑定短信应用');
if (!String(profile.companyName ?? '').trim()) missing.push('缺少公司名称');
if (!String(profile.creditCode ?? '').trim()) missing.push('缺少统一社会信用代码');
if (!String(profile.legalPersonName ?? '').trim()) missing.push('缺少法人姓名');
if (!String(profile.responsibleName ?? '').trim()) missing.push('缺少责任人姓名');
if (!String(profile.responsiblePhone ?? '').trim()) missing.push('缺少责任人手机号');
const profileHasFile = Object.values(profile).some((value) => Boolean(asRecord(value).fileObjectId));
if (!profileHasFile && item.materials.length === 0) missing.push('缺少资质文件');
const signatureValues = asRecord(payload.signatureReportValues);
const requiredFields = reportRequirementFields(payload)
.filter((field) => field.required && field.reportTypes.some((type) => type === 'signature' || type === 'both'));
for (const field of requiredFields) {
if (!hasReportValue(signatureValues[field.code])) missing.push(`缺少${field.name}`);
}
return reviewPreflight('signature', item, {
identity: { name: item.name, id: item.id, tenant: item.tenant.name, application: item.application?.name ?? '未绑定应用' },
blockedReasons: missing,
impacts: ['通过后签名将进入报备资格链路', '已绑定模板和后续发送资格可能受此决定影响'],
materialSummary: { qualificationFiles: item.materials.length + (profileHasFile ? 1 : 0), missingCount: missing.length },
materialSummary: {
configuredRequiredFields: requiredFields.length,
submittedFields: Object.values(signatureValues).filter(hasReportValue).length,
qualificationFiles: item.materials.length + Object.values(signatureValues).filter((value) => Boolean(asRecord(value).fileObjectId)).length,
missingCount: missing.length,
},
});
}
@@ -156,3 +159,30 @@ function normalizeIdempotencyKey(value: string) {
function asRecord(value: unknown): Record<string, unknown> {
return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {};
}
function reportRequirementFields(payload: Record<string, unknown>) {
const snapshot = asRecord(payload.reportRequirementSnapshot);
if (!Array.isArray(snapshot.fields)) return [];
return snapshot.fields.flatMap((value) => {
const field = asRecord(value);
const code = typeof field.code === 'string' ? field.code.trim() : '';
if (!code) return [];
const reportTypes = Array.isArray(field.reportTypes)
? field.reportTypes.filter((type): type is string => typeof type === 'string')
: [];
return [{
code,
name: typeof field.name === 'string' && field.name.trim() ? field.name.trim() : code,
required: field.required === true,
reportTypes,
}];
});
}
function hasReportValue(value: unknown) {
if (value && typeof value === 'object' && !Array.isArray(value)) {
const record = asRecord(value);
return Boolean(record.fileObjectId || record.fieldValue || record.value);
}
return value !== undefined && value !== null && String(value).trim().length > 0;
}