import { buildTamRequestPayload, tamRequest, type TamRequestPayload, type TamResponse, } from '@/api/tam' import { ROLE_IDS } from '@/config/permissions' export type ForeignForecastRecord = { /** 授权标志。 */ authorization?: string /** 账户行。 */ bankAcct?: string /** 旧接口业务类型字段,详情接口暂时兼容使用。 */ busiType?: string /** 币种。 */ ccy?: string /** 客户账号。 */ clientAcct?: string /** 客户名称。 */ clientName?: string /** 收款账号。 */ competAcct?: string /** 交易对手 Swift Code。 */ competAcctSc?: string /** 收款人名称。 */ competName?: string /** 单证业务编号。 */ docBusinessno?: string /** 兼容列表接口可能返回的旧字段名。 */ docbusinessno?: string /** 落地机构。 */ groundBranch?: string /** 落地机构名称。 */ groundBranchName?: string /** 中间行 Swift Code。 */ midBankSc?: string /** 结汇、购汇或现汇。 */ originalForeign?: string /** 收支方向。 */ payDirec?: string /** 汇款路径。 */ paymentRoute?: string /** 联系电话。 */ phoneNo?: string /** 预报金额,接口按元级金额返回,页面转换为万元级展示。 */ predAmt?: string /** 预报人编号。 */ predCode?: string /** 预报时间。 */ predDate?: string /** 预报机构。 */ predDept?: string /** 预报人。 */ predName?: string /** 预报流水号,后续详情查询主键。 */ predRefNo?: string /** 预报状态。 */ predStatus?: string /** 预报类型。 */ predType?: string /** 预报方式。 */ predWay?: string /** 交易对手行名称。 */ rcvBank?: string /** 收款账号。 */ rcvAcct?: string /** 收款人名称。 */ rcvName?: string /** 交易对手行 Swift Code。 */ rcvBankSc?: string /** 备注。 */ remark?: string /** 起息日期。 */ tranDate?: string /** 业务类型。 */ tranType?: string /** 未核销金额。 */ unverifyAmt?: string /** 审批时间。 */ updateTime?: string /** 核销金额。 */ verifyAmt?: string /** 核销状态。 */ verifyStatus?: string /** 兼容旧接口可能返回的币种字段。 */ currency?: string currencyCode?: string currCode?: string curType?: string tranCcy?: string /** 兼容旧接口返回字段。 */ clientType?: string bankSwift?: string bicCode?: string routeCode?: string swiftCode?: string } export type ForeignForecastQueryForm = { /** 起息日。 */ tranDate: string /** 机构名称。 */ orgName?: string /** 币种。 */ ccy?: string /** 业务类型。 */ tranType?: string /** 预报状态,可多选;请求时使用逗号拼接。 */ predStatus?: string[] /** 筛选 FTU 数据,否为空、是为 1。 */ filter?: string /** 起始金额,由金额组件以元为单位输出。 */ startAmt?: string /** 截止金额,由金额组件以元为单位输出。 */ endAmt?: string } /** 外币预报新增、修改页面提交的业务字段。 */ export type ForeignForecastMutationForm = { bankAcct: string ccy: string clientAcct: string clientName: string clientType: string competAcct: string competAcctSc: string competName: string docbusinessno: string groundBranch: string groundBranchName: string midBankSc: string originalForeign: string payDirec: string paymentRoute: string phoneNo: string predAmt: string predCode: string predDate: string predDept: string predName: string purpose: string rcvBank: string rcvBankSc: string remark: string tranDate: string tranType: string } /** 审批查询不开放预报状态,由当前默认角色自动决定。 */ export type ForeignForecastApprovalQueryForm = Omit export type ForeignForecastQueryPayload = { appHead: TamRequestPayload['appHead'] body: ForeignForecastQueryBody head: TamRequestPayload['head'] } export type ForeignForecastQueryResult = { body: ForeignForecastQueryResultBody head: TamResponse['head'] } export type ForeignForecastCreateBody = ForeignForecastMutationForm & { /** 授权标志,新增接口按约定传空。 */ authoFlag: string } export type ForeignForecastCreatePayload = { appHead: TamRequestPayload['appHead'] body: ForeignForecastCreateBody head: TamRequestPayload['head'] } export type ForeignForecastCreateResult = { body: Record head: TamResponse>['head'] } export type ForeignForecastUpdateBody = ForeignForecastMutationForm & { /** 用户权限,修改接口按约定传空。 */ junge: string /** 预报流水号。 */ predRefNo: string } export type ForeignForecastUpdatePayload = { appHead: TamRequestPayload['appHead'] body: ForeignForecastUpdateBody head: TamRequestPayload['head'] } export type ForeignForecastUpdateResult = { body: Record head: TamResponse>['head'] } export type ForeignForecastDetailPayload = { appHead: TamRequestPayload['appHead'] body: ForeignForecastDetailBody head: TamRequestPayload['head'] } export type ForeignForecastDetailResult = { body: ForeignForecastDetailRecord head: TamResponse['head'] } export type ForeignForecastBankAccountQueryBody = { /** 币种。 */ ccy: string /** 汇款路径。 */ paymentRoute: string /** 业务类型。 */ tranType: string } export type ForeignForecastBankAccountQueryResult = TamResponse<{ bankAcctList: string[] }> export type ForeignForecastHolidayCheckBody = { /** 币种。 */ ccy: string /** 起息日,格式 YYYYMMDD。 */ tranDate: string } export type ForeignForecastHolidayCheckResult = TamResponse<{ /** HF00 表示所选日期为该币种节假日。 */ flag: string }> export type ForeignForecastApprovalDecision = 'approve' | 'reject' export type ForeignForecastApprovalPayload = { appHead: TamRequestPayload['appHead'] body: ForeignForecastApprovalBody head: TamRequestPayload['head'] } export type ForeignForecastApprovalResult = { body: Record head: TamResponse>['head'] } type ForeignForecastQueryBody = { amtOrder: number | '' authorization: string ccy: string clientName: string endAmt: string filter: string opType: string orgName: string originalForeign: string payDirec: string predOrder: number | '' predStatus: string predWay: string startAmt: string timeOrder: number | '' tranDate: string tranType: string verifyStatus: string } type ForeignForecastQueryResultBody = { resultInfos: ForeignForecastRecord[] totalCount: string totalPage: string } type ForeignForecastDetailBody = { /** 预报流水号,详情查询主键。 */ predRefNo: string } type ForeignForecastApprovalBody = { /** 审批结果:1-通过,0-拒绝。 */ flag: '0' | '1' /** 审批数据,多个流水号时使用逗号拼接。 */ predRefNos: string } export type ForeignForecastDetailRecord = ForeignForecastRecord & { /** 出票日 */ billDate?: string /** 票号 */ billNo?: string /** 交易对手账号 */ competAcct?: string /** 额度标志 */ eduFlag?: string /** 落地机构代码 */ groundBranchCode?: string /** 联系人 */ linkMan?: string /** 支付渠道 */ payChannel?: string /** 收支方向 */ payDirec?: string /** 联系电话 */ phoneNo?: string /** 预报机构 */ predBranch?: string /** 预报机构名称 */ predBranchName?: string /** 预报人员编号 */ predCode?: string /** 预报日期 */ predDate?: string /** 预报人员姓名 */ predName?: string /** 用途 */ purpose?: string /** 备注 */ remark?: string /** 标准名称 */ standardName?: string /** 已核销金额 */ verifyAmt?: string } type QueryOptions = { form: ForeignForecastQueryForm pageIndex: number pageSize: number } type ApprovalQueryOptions = { form: ForeignForecastApprovalQueryForm pageIndex: number pageSize: number primaryRoleId: string } const QUERY_TRAN_CODE = '/TAM/0001/140201001' const BANK_ACCOUNT_QUERY_TRAN_CODE = '/TAM/0001/140201002' const HOLIDAY_CHECK_TRAN_CODE = '/TAM/0001/140201003' const DETAIL_TRAN_CODE = '/TAM/0001/140201004' const CREATE_TRAN_CODE = '/TAM/0001/120201001' const UPDATE_TRAN_CODE = '/TAM/0001/120201002' const APPROVAL_TRAN_CODE = '/TAM/0001/120201004' const HEAD_OFFICE_APPROVAL_STATUS_VALUES = ['2', '7'] as const const BRANCH_APPROVAL_STATUS_VALUES = ['1', '6'] as const const APPROVAL_FLAG_MAP: Record = { approve: '1', reject: '0', } /** * 根据多角色规则选出的默认角色返回其可审批状态。 * 001 与 006 处理总行确认,007 处理分行确认。 */ export function resolveForeignApprovalStatusValues(primaryRoleId: string): string[] { if ( primaryRoleId === ROLE_IDS.systemAdmin || primaryRoleId === ROLE_IDS.headOfficeManager ) { return [...HEAD_OFFICE_APPROVAL_STATUS_VALUES] } if (primaryRoleId === ROLE_IDS.branchManager) { return [...BRANCH_APPROVAL_STATUS_VALUES] } return [] } export function buildForeignForecastApprovalQueryPayload({ form, pageIndex, pageSize, primaryRoleId, }: ApprovalQueryOptions): ForeignForecastQueryPayload { const predStatus = resolveForeignApprovalStatusValues(primaryRoleId) if (!predStatus.length) { throw new Error('当前角色不支持外币头寸预报审批') } return buildForeignForecastQueryPayload({ form: { ...form, predStatus, }, pageIndex, pageSize, }) } export function buildForeignForecastQueryPayload({ form, pageIndex, pageSize, }: QueryOptions): ForeignForecastQueryPayload { const tranDate = normalizeDate(form.tranDate) return buildTamRequestPayload({ tranCode: QUERY_TRAN_CODE, pageIndex, pageSize, body: { amtOrder: '', authorization: '', ccy: form.ccy || '', clientName: '', endAmt: toRequestAmount(form.endAmt), filter: form.filter || '', opType: '', orgName: form.orgName || '', originalForeign: '', payDirec: '', predOrder: '', predStatus: form.predStatus?.join(',') || '', predWay: '', startAmt: toRequestAmount(form.startAmt), timeOrder: '', tranDate, tranType: form.tranType || '', verifyStatus: '', }, }) } export function buildForeignForecastCreatePayload( form: ForeignForecastMutationForm, ): ForeignForecastCreatePayload { return buildTamRequestPayload({ tranCode: CREATE_TRAN_CODE, body: { authoFlag: '', ...normalizeForeignForecastMutationForm(form), }, }) } export async function createForeignForecast( payload: ForeignForecastCreatePayload, ): Promise { return tamRequest>(payload) } export function buildForeignForecastUpdatePayload( predRefNo: string, form: ForeignForecastMutationForm, ): ForeignForecastUpdatePayload { return buildTamRequestPayload({ tranCode: UPDATE_TRAN_CODE, body: { ...normalizeForeignForecastMutationForm(form), junge: '', predRefNo: predRefNo.trim(), }, }) } export async function updateForeignForecast( payload: ForeignForecastUpdatePayload, ): Promise { return tamRequest>(payload) } export async function queryForeignForecastPage( payload: ForeignForecastQueryPayload, ): Promise { return tamRequest(payload) } export function buildForeignForecastBankAccountQueryPayload( body: ForeignForecastBankAccountQueryBody, ): TamRequestPayload { return buildTamRequestPayload({ tranCode: BANK_ACCOUNT_QUERY_TRAN_CODE, body: { ccy: body.ccy.trim(), paymentRoute: body.paymentRoute.trim(), tranType: body.tranType.trim(), }, }) } export async function queryForeignForecastBankAccounts( payload: TamRequestPayload, ): Promise { return tamRequest( payload, ) } export function buildForeignForecastHolidayCheckPayload( body: ForeignForecastHolidayCheckBody, ): TamRequestPayload { return buildTamRequestPayload({ tranCode: HOLIDAY_CHECK_TRAN_CODE, body: { ccy: body.ccy.trim(), tranDate: normalizeDate(body.tranDate.trim()), }, }) } export async function checkForeignForecastHoliday( payload: TamRequestPayload, ): Promise { return tamRequest(payload) } export function buildForeignForecastDetailPayload(predRefNo: string): ForeignForecastDetailPayload { return buildTamRequestPayload({ tranCode: DETAIL_TRAN_CODE, body: { predRefNo, }, }) } export async function queryForeignForecastDetail( payload: ForeignForecastDetailPayload, ): Promise { return tamRequest(payload) } export function buildForeignForecastApprovalPayload( predRefNos: string, decision: ForeignForecastApprovalDecision, ): ForeignForecastApprovalPayload { return buildTamRequestPayload({ tranCode: APPROVAL_TRAN_CODE, body: { flag: APPROVAL_FLAG_MAP[decision], predRefNos, }, }) } export async function submitForeignForecastApproval( payload: ForeignForecastApprovalPayload, ): Promise { return tamRequest>(payload) } function normalizeDate(value: string) { if (/^\d{8}$/.test(value)) return value return value.replaceAll('-', '') } function toRequestAmount(value?: string) { if (!value?.trim()) return '' const amount = Number(value) return Number.isFinite(amount) ? String(Math.round(amount)) : '' } function normalizeForeignForecastMutationForm( form: ForeignForecastMutationForm, ): ForeignForecastMutationForm { return { bankAcct: form.bankAcct.trim(), ccy: form.ccy.trim(), clientAcct: form.clientAcct.trim(), clientName: form.clientName.trim(), clientType: form.clientType.trim(), competAcct: form.competAcct.trim(), competAcctSc: form.competAcctSc.trim(), competName: form.competName.trim(), docbusinessno: form.docbusinessno.trim(), groundBranch: form.groundBranch.trim(), groundBranchName: form.groundBranchName.trim(), midBankSc: form.midBankSc.trim(), originalForeign: form.originalForeign.trim(), payDirec: form.payDirec.trim(), paymentRoute: form.paymentRoute.trim(), phoneNo: form.phoneNo.trim(), predAmt: form.predAmt.trim().replaceAll(',', ''), predCode: form.predCode.trim(), predDate: normalizeDate(form.predDate.trim()), predDept: form.predDept.trim(), predName: form.predName.trim(), purpose: form.purpose.trim(), rcvBank: form.rcvBank.trim(), rcvBankSc: form.rcvBankSc.trim(), remark: form.remark.trim(), tranDate: normalizeDate(form.tranDate.trim()), tranType: form.tranType.trim(), } }