feat: migrate app routes and business modules
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import { createRequestError } from './request-client.js'
|
||||
import { normalizeResponseText } from './response-normalizers.js'
|
||||
import {
|
||||
assertPlainPayload,
|
||||
normalizeOptionalText,
|
||||
normalizeResourcePathId
|
||||
} from './request-normalizers.js'
|
||||
import { normalizeGenealogyPathId } from './genealogy-contract.js'
|
||||
|
||||
export const JOIN_APPLICATION_STATUS = Object.freeze({
|
||||
PENDING: '0',
|
||||
APPROVED: '1',
|
||||
REJECTED: '2',
|
||||
CANCELLED: '3'
|
||||
})
|
||||
|
||||
export const JOIN_APPLICATION_STATUS_LABELS = Object.freeze({
|
||||
[JOIN_APPLICATION_STATUS.PENDING]: '审核中',
|
||||
[JOIN_APPLICATION_STATUS.APPROVED]: '已通过',
|
||||
[JOIN_APPLICATION_STATUS.REJECTED]: '未通过',
|
||||
[JOIN_APPLICATION_STATUS.CANCELLED]: '已撤回'
|
||||
})
|
||||
|
||||
const joinApplicationAuditStatuses = new Set([
|
||||
JOIN_APPLICATION_STATUS.APPROVED,
|
||||
JOIN_APPLICATION_STATUS.REJECTED
|
||||
])
|
||||
|
||||
export const normalizeJoinApplicationPayload = (payload) => {
|
||||
assertPlainPayload(payload, new Set(['applicantName', 'phone', 'relationDesc', 'applyReason']), '加入申请请求')
|
||||
const normalizedPayload = {}
|
||||
for (const field of ['applicantName', 'phone', 'relationDesc', 'applyReason']) {
|
||||
const normalizedText = normalizeOptionalText(payload[field], field)
|
||||
if (normalizedText) normalizedPayload[field] = normalizedText
|
||||
}
|
||||
return normalizedPayload
|
||||
}
|
||||
|
||||
export const normalizeGenealogyInvitationToken = (value) => {
|
||||
if (typeof value !== 'string') throw new TypeError('邀请码必须是文本')
|
||||
const token = value.trim()
|
||||
if (!token) throw new TypeError('请输入邀请码')
|
||||
if (token.length > 128) throw new TypeError('邀请码长度不能超过128个字符')
|
||||
return token
|
||||
}
|
||||
|
||||
export const normalizeGenealogyInvitationRedeemPayload = (payload) => {
|
||||
assertPlainPayload(payload, new Set(['token']), '家谱邀请码兑换请求')
|
||||
return { token: normalizeGenealogyInvitationToken(payload.token) }
|
||||
}
|
||||
|
||||
export const normalizeGenealogyInvitation = (value, expectedStatus = '') => {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
throw createRequestError('家谱邀请码响应无效', 'GENEALOGY_INVITATION_RESPONSE_INVALID')
|
||||
}
|
||||
const genealogyId = normalizeGenealogyPathId(value.genealogyId)
|
||||
const genealogyName = normalizeResponseText(value.genealogyName, 'genealogyName')
|
||||
const status = normalizeResponseText(value.status, 'status')
|
||||
const expiresAt = normalizeResponseText(value.expiresAt, 'expiresAt')
|
||||
if (!genealogyName || !status || !expiresAt) {
|
||||
throw createRequestError('家谱邀请码响应缺少可展示信息', 'GENEALOGY_INVITATION_RESPONSE_INVALID')
|
||||
}
|
||||
if (expectedStatus && status !== expectedStatus) {
|
||||
throw createRequestError('家谱邀请码状态与当前操作不匹配', 'GENEALOGY_INVITATION_RESPONSE_INVALID')
|
||||
}
|
||||
const redemptionResult = normalizeResponseText(value.redemptionResult, 'redemptionResult')
|
||||
if (expectedStatus === 'REDEEMED' && !['DIRECT_MEMBER', 'PENDING_APPLY'].includes(redemptionResult)) {
|
||||
throw createRequestError('家谱邀请码兑换结果无效', 'GENEALOGY_INVITATION_RESPONSE_INVALID')
|
||||
}
|
||||
return {
|
||||
genealogyId,
|
||||
genealogyName,
|
||||
status,
|
||||
expiresAt,
|
||||
redemptionResult
|
||||
}
|
||||
}
|
||||
|
||||
export const normalizeIssuedGenealogyInvitation = (value) => {
|
||||
const invitation = normalizeGenealogyInvitation(value, 'ACTIVE')
|
||||
return {
|
||||
...invitation,
|
||||
token: normalizeGenealogyInvitationToken(value.token)
|
||||
}
|
||||
}
|
||||
|
||||
const genealogyInvitationStatuses = new Set(['ACTIVE', 'REDEEMED', 'REVOKED', 'EXPIRED'])
|
||||
|
||||
export const normalizeMyGenealogyInvitations = (value) => {
|
||||
if (!Array.isArray(value)) {
|
||||
throw createRequestError('我的家谱邀请响应不是列表', 'GENEALOGY_INVITATION_RESPONSE_INVALID')
|
||||
}
|
||||
const invitations = value.map((item) => {
|
||||
const invitation = normalizeGenealogyInvitation(item)
|
||||
const id = normalizeResourcePathId(item.inviteId, '家谱邀请标识')
|
||||
if (!genealogyInvitationStatuses.has(invitation.status)) {
|
||||
throw createRequestError('家谱邀请状态无效', 'GENEALOGY_INVITATION_RESPONSE_INVALID')
|
||||
}
|
||||
return { id, ...invitation }
|
||||
})
|
||||
if (new Set(invitations.map((item) => item.id)).size !== invitations.length) {
|
||||
throw createRequestError('我的家谱邀请响应包含重复标识', 'GENEALOGY_INVITATION_RESPONSE_INVALID')
|
||||
}
|
||||
return invitations
|
||||
}
|
||||
|
||||
export const normalizeJoinAuditPayload = (payload) => {
|
||||
assertPlainPayload(payload, new Set(['status', 'auditRemark']), '加入申请审核请求')
|
||||
const status = normalizeOptionalText(payload.status, '审核状态')
|
||||
if (!joinApplicationAuditStatuses.has(status)) {
|
||||
throw new TypeError('加入申请审核状态只能是通过或拒绝')
|
||||
}
|
||||
const normalizedPayload = { status }
|
||||
const auditRemark = normalizeOptionalText(payload.auditRemark, '审核备注')
|
||||
if (auditRemark) normalizedPayload.auditRemark = auditRemark
|
||||
return normalizedPayload
|
||||
}
|
||||
Reference in New Issue
Block a user