154 lines
7.4 KiB
JavaScript
154 lines
7.4 KiB
JavaScript
import { createRequestError } from './request-client.js'
|
|
import {
|
|
normalizeOptionalNumericId,
|
|
normalizeOptionalResponseText
|
|
} from './response-normalizers.js'
|
|
import {
|
|
assertPlainPayload,
|
|
normalizeOptionalNormalDisableStatus,
|
|
normalizeOptionalText,
|
|
normalizeResourcePathId
|
|
} from './request-normalizers.js'
|
|
import { normalizeBusinessOptionProjection } from './business-dictionary-contract.js'
|
|
|
|
const normalizePersonDocumentText = (value, field) =>
|
|
normalizeOptionalResponseText(value, field, '重要证件响应', 'PERSON_DOCUMENT_RESPONSE_INVALID')
|
|
|
|
export const PERSON_DOCUMENT_TYPE_OPTIONS = Object.freeze([
|
|
Object.freeze({ value: 'id_card', label: '身份证' }),
|
|
Object.freeze({ value: 'household_register', label: '户口簿' }),
|
|
Object.freeze({ value: 'birth_certificate', label: '出生证明' }),
|
|
Object.freeze({ value: 'marriage_certificate', label: '结婚证' }),
|
|
Object.freeze({ value: 'other', label: '其他证件' })
|
|
])
|
|
|
|
export const PERSON_DOCUMENT_RESOURCE_USAGE = Object.freeze({
|
|
FRONT: 'FRONT',
|
|
BACK: 'BACK',
|
|
ATTACHMENT: 'ATTACHMENT'
|
|
})
|
|
|
|
export const PERSON_DOCUMENT_RESOURCE_USAGE_LABELS = Object.freeze({
|
|
[PERSON_DOCUMENT_RESOURCE_USAGE.FRONT]: '正面',
|
|
[PERSON_DOCUMENT_RESOURCE_USAGE.BACK]: '反面',
|
|
[PERSON_DOCUMENT_RESOURCE_USAGE.ATTACHMENT]: '附件'
|
|
})
|
|
|
|
const personDocumentResourceUsages = new Set(
|
|
Object.values(PERSON_DOCUMENT_RESOURCE_USAGE)
|
|
)
|
|
|
|
export const normalizePersonDocumentResource = (value) => {
|
|
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
throw createRequestError('证件文件响应无效', 'PERSON_DOCUMENT_RESPONSE_INVALID')
|
|
}
|
|
const usageType = normalizePersonDocumentText(value.usageType, 'usageType')
|
|
if (!personDocumentResourceUsages.has(usageType)) {
|
|
throw createRequestError('证件文件用途无效', 'PERSON_DOCUMENT_RESPONSE_INVALID')
|
|
}
|
|
return {
|
|
resourceId: normalizeResourcePathId(value.resourceId, '证件文件标识'),
|
|
usageType,
|
|
sortOrder: Number.isSafeInteger(value.sortOrder) ? value.sortOrder : null,
|
|
status: normalizePersonDocumentText(value.status, 'status')
|
|
}
|
|
}
|
|
|
|
export const normalizePersonDocument = (value, expectedGenealogyId) => {
|
|
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
throw createRequestError('重要证件响应无效', 'PERSON_DOCUMENT_RESPONSE_INVALID')
|
|
}
|
|
const genealogyId = normalizeResourcePathId(value.genealogyId, '家谱标识')
|
|
if (genealogyId !== expectedGenealogyId) {
|
|
throw createRequestError('重要证件归属与请求不匹配', 'PERSON_DOCUMENT_RESPONSE_INVALID')
|
|
}
|
|
const documentType = normalizeBusinessOptionProjection(
|
|
value.documentType,
|
|
value.documentTypeLabel,
|
|
value.documentTypeOptionState,
|
|
'重要证件类型',
|
|
'PERSON_DOCUMENT_RESPONSE_INVALID'
|
|
)
|
|
const documentTitle = normalizePersonDocumentText(value.documentTitle, 'documentTitle')
|
|
if (!documentTitle) throw createRequestError('重要证件缺少标题', 'PERSON_DOCUMENT_RESPONSE_INVALID')
|
|
for (const field of ['contentProtected', 'contentUnlocked', 'canEdit', 'canDelete']) {
|
|
if (typeof value[field] !== 'boolean') {
|
|
throw createRequestError(`重要证件权限字段 ${field} 无效`, 'PERSON_DOCUMENT_RESPONSE_INVALID')
|
|
}
|
|
}
|
|
if (!Array.isArray(value.resources)) {
|
|
throw createRequestError('重要证件文件列表无效', 'PERSON_DOCUMENT_RESPONSE_INVALID')
|
|
}
|
|
return {
|
|
documentId: normalizeResourcePathId(value.documentId, '重要证件标识'),
|
|
genealogyId,
|
|
lineagePersonId: normalizeResourcePathId(value.lineagePersonId, '世系人物标识'),
|
|
lineagePersonName: normalizePersonDocumentText(value.lineagePersonName, 'lineagePersonName'),
|
|
documentType: documentType.value,
|
|
documentTypeLabel: documentType.label,
|
|
documentTypeOptionState: documentType.state,
|
|
documentTitle,
|
|
maskedIdentifier: normalizePersonDocumentText(value.maskedIdentifier, 'maskedIdentifier'),
|
|
description: normalizePersonDocumentText(value.description, 'description'),
|
|
uploaderUserId: normalizeOptionalNumericId(value.uploaderUserId, '上传人标识', 'PERSON_DOCUMENT_RESPONSE_INVALID'),
|
|
sortOrder: Number.isSafeInteger(value.sortOrder) ? value.sortOrder : null,
|
|
status: normalizePersonDocumentText(value.status, 'status'),
|
|
contentProtected: value.contentProtected,
|
|
contentUnlocked: value.contentUnlocked,
|
|
canEdit: value.canEdit,
|
|
canDelete: value.canDelete,
|
|
resources: value.resources.map(normalizePersonDocumentResource)
|
|
}
|
|
}
|
|
|
|
export const normalizePersonDocuments = (value, expectedGenealogyId) => {
|
|
if (!Array.isArray(value)) throw createRequestError('重要证件响应不是列表', 'PERSON_DOCUMENT_RESPONSE_INVALID')
|
|
const rows = value.map((item) => normalizePersonDocument(item, expectedGenealogyId))
|
|
if (new Set(rows.map((item) => item.documentId)).size !== rows.length) {
|
|
throw createRequestError('重要证件包含重复标识', 'PERSON_DOCUMENT_RESPONSE_INVALID')
|
|
}
|
|
return rows
|
|
}
|
|
|
|
export const normalizePersonDocumentPayload = (payload) => {
|
|
assertPlainPayload(payload, new Set(['lineagePersonId', 'documentType', 'documentTitle', 'maskedIdentifier', 'description', 'sortOrder', 'status']), '重要证件请求')
|
|
const documentType = normalizeOptionalText(payload.documentType, 'documentType')
|
|
if (!documentType) throw new TypeError('请选择有效的证件类型')
|
|
const documentTitle = normalizeOptionalText(payload.documentTitle, 'documentTitle')
|
|
if (!documentTitle) throw new TypeError('请填写证件标题')
|
|
if (documentTitle.length > 100) throw new TypeError('证件标题不能超过100个字符')
|
|
const normalizedPayload = {
|
|
lineagePersonId: normalizeResourcePathId(payload.lineagePersonId, '世系人物标识'),
|
|
documentType,
|
|
documentTitle
|
|
}
|
|
for (const [field, limit] of [['maskedIdentifier', 100], ['description', 1000]]) {
|
|
if (!Object.prototype.hasOwnProperty.call(payload, field)) continue
|
|
if (typeof payload[field] !== 'string') throw new TypeError(`${field}必须是字符串`)
|
|
const normalizedText = payload[field].trim()
|
|
if (normalizedText.length > limit) throw new TypeError(`${field} 超出长度限制`)
|
|
normalizedPayload[field] = normalizedText
|
|
}
|
|
if (payload.sortOrder !== undefined && payload.sortOrder !== null && payload.sortOrder !== '') {
|
|
const sortOrder = typeof payload.sortOrder === 'number' ? payload.sortOrder : Number(payload.sortOrder)
|
|
if (!Number.isSafeInteger(sortOrder)) throw new TypeError('sortOrder必须是安全整数')
|
|
normalizedPayload.sortOrder = sortOrder
|
|
}
|
|
const status = normalizeOptionalNormalDisableStatus(payload.status, '证件状态')
|
|
if (status) normalizedPayload.status = status
|
|
return normalizedPayload
|
|
}
|
|
|
|
export const normalizePersonDocumentResourcePayload = (payload) => {
|
|
assertPlainPayload(payload, new Set(['ossId', 'usageType', 'sortOrder']), '证件文件请求')
|
|
if (!personDocumentResourceUsages.has(payload.usageType)) throw new TypeError('请选择有效的证件文件用途')
|
|
const ossId = normalizeResourcePathId(payload.ossId, 'OSS文件标识')
|
|
const normalizedPayload = { ossId, usageType: payload.usageType }
|
|
if (payload.sortOrder !== undefined && payload.sortOrder !== null && payload.sortOrder !== '') {
|
|
const sortOrder = typeof payload.sortOrder === 'number' ? payload.sortOrder : Number(payload.sortOrder)
|
|
if (!Number.isSafeInteger(sortOrder)) throw new TypeError('sortOrder必须是安全整数')
|
|
normalizedPayload.sortOrder = sortOrder
|
|
}
|
|
return normalizedPayload
|
|
}
|