1.1.49 分款审核页面、分款流程优化。

dev
yinq 3 weeks ago
parent e7cdde97f6
commit 86a7e88551

@ -74,11 +74,6 @@ export interface FinAccountInstallmentVO {
*/ */
managerNickNames?: string; managerNickNames?: string;
/**
*
*/
canAllocate?: boolean;
} }
export interface FinAccountInstallmentForm extends BaseEntity { export interface FinAccountInstallmentForm extends BaseEntity {
@ -147,11 +142,6 @@ export interface FinAccountInstallmentForm extends BaseEntity {
*/ */
managerNickNames?: string; managerNickNames?: string;
/**
*
*/
canAllocate?: boolean;
/** 流程编码 */ /** 流程编码 */
flowCode?: string; flowCode?: string;
@ -163,20 +153,10 @@ export interface FinAccountInstallmentForm extends BaseEntity {
} }
/** 派发给客户经理(含流程启动参数,前端组装) */ /** 派发给客户经理 */
export interface FinAccountInstallmentDispatchForm { export interface FinAccountInstallmentDispatchForm {
accountInstallmentIds: Array<string | number>; accountInstallmentIds: Array<string | number>;
managerUserIds: Array<string | number>; managerUserIds: Array<string | number>;
/** 流程编码 FKSH */
flowCode?: string;
/** 流程变量 */
variables?: Record<string, any>;
/** 各回款流程业务扩展businessId=回款主键) */
flowBizList?: Array<{
businessId?: string;
businessCode?: string;
businessTitle?: string;
}>;
} }
export interface FinAccountInstallmentQuery extends PageQuery { export interface FinAccountInstallmentQuery extends PageQuery {

@ -17,11 +17,10 @@
<template #header> <template #header>
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div style="text-align: left; font-weight: bold; font-size: 24px">{{ pageTitle }}</div> <div style="text-align: left; font-weight: bold; font-size: 24px">{{ pageTitle }}</div>
<el-button v-if="canAllocate" type="primary" @click="handleAddDetail"> <el-button v-if="canEditDetail" type="primary" @click="handleAddDetail">
<el-icon class="mr-1"><Plus /></el-icon> <el-icon class="mr-1"><Plus /></el-icon>
新增分款 新增分款
</el-button> </el-button>
<el-tag v-else-if="routeParams.type === 'allocate'" type="info">{{ allocateHintText }}</el-tag>
</div> </div>
</template> </template>
@ -71,7 +70,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip /> <el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
<el-table-column v-if="canAllocate" label="操作" align="center" width="100" fixed="right"> <el-table-column v-if="canEditDetail" label="操作" align="center" width="100" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<el-button link type="primary" size="small" @click="handleEditDetail(row)"></el-button> <el-button link type="primary" size="small" @click="handleEditDetail(row)"></el-button>
<el-button link type="danger" size="small" @click="handleDeleteDetail(row)"></el-button> <el-button link type="danger" size="small" @click="handleDeleteDetail(row)"></el-button>
@ -80,7 +79,7 @@
</el-table> </el-table>
<el-empty <el-empty
v-if="!detailLoading && !detailList.length" v-if="!detailLoading && !detailList.length"
:description="canAllocate ? '暂无分款明细,请点击新增分款添加' : '暂无分款明细'" :description="canEditDetail ? '暂无分款明细,请点击新增分款添加' : '暂无分款明细'"
class="mt-3" class="mt-3"
/> />
</el-card> </el-card>
@ -197,12 +196,6 @@ const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
const taskVariables = ref<Record<string, any>>({}); const taskVariables = ref<Record<string, any>>({});
const FLOW_STATUS = { DRAFT: 'draft', WAITING: 'waiting', FINISH: 'finish', BACK: 'back', CANCEL: 'cancel' };
const INSTALLMENT_STATUS = { NOT_ALLOCATED: '0', DISPATCHED: '1', COMPLETE: '2' };
const isFlowEditable = (flowStatus?: string) =>
!flowStatus || flowStatus === FLOW_STATUS.DRAFT || flowStatus === FLOW_STATUS.BACK || flowStatus === FLOW_STATUS.CANCEL;
const initFormData: FinAccountInstallmentForm = { const initFormData: FinAccountInstallmentForm = {
accountInstallmentId: undefined, accountInstallmentId: undefined,
installmentCode: undefined, installmentCode: undefined,
@ -216,7 +209,6 @@ const initFormData: FinAccountInstallmentForm = {
accountManagerIds: undefined, accountManagerIds: undefined,
managerUserIds: [], managerUserIds: [],
managerNickNames: undefined, managerNickNames: undefined,
canAllocate: undefined
}; };
const form = ref<FinAccountInstallmentForm>({ ...initFormData }); const form = ref<FinAccountInstallmentForm>({ ...initFormData });
@ -228,20 +220,8 @@ const pageTitle = computed(() => {
return '客户分款'; return '客户分款';
}); });
/** 客户经理分款:查看模式只读,审批/分款模式在 canAllocate 时可维护明细 */ /** 仅分款审核页type=approval待办审批进入可维护分款明细 */
const canAllocate = computed(() => form.value.canAllocate === true && routeParams.value.type !== 'view'); const canEditDetail = computed(() => routeParams.value.type === 'approval');
const allocateHintText = computed(() => {
if (form.value.canAllocate) return '';
if (isFlowEditable(form.value.flowStatus) && form.value.installmentStatus === INSTALLMENT_STATUS.NOT_ALLOCATED) {
return '请先由财务派发给客户经理';
}
if (form.value.flowStatus === FLOW_STATUS.FINISH || form.value.installmentStatus === INSTALLMENT_STATUS.COMPLETE) {
return '分款已完成';
}
if (form.value.flowStatus !== FLOW_STATUS.WAITING) return '流程未处于待处理状态';
return '您无权操作该回款分款';
});
const allocatedAmount = computed(() => const allocatedAmount = computed(() =>
Number((detailList.value || []).reduce((sum, item) => sum + Number(item.detailAmount || 0), 0)) Number((detailList.value || []).reduce((sum, item) => sum + Number(item.detailAmount || 0), 0))
@ -249,6 +229,27 @@ const allocatedAmount = computed(() =>
const remainingAmount = computed(() => Number(form.value.paymentAmount || 0) - allocatedAmount.value); const remainingAmount = computed(() => Number(form.value.paymentAmount || 0) - allocatedAmount.value);
/** 分款金额与回款金额平衡容差(元) */
const ALLOCATION_AMOUNT_EPS = 0.005;
/** 提交/审批前校验:分款总额须等于回款金额 */
const validateAllocationBeforeSubmit = (): boolean => {
const remain = remainingAmount.value;
if (remain < -ALLOCATION_AMOUNT_EPS) {
proxy?.$modal.msgWarning(`分款金额超出回款金额,已超出 ¥${formatMoney(Math.abs(remain))},无法提交`);
return false;
}
if (remain > ALLOCATION_AMOUNT_EPS) {
proxy?.$modal.msgWarning(`分款金额不足回款金额,还差 ¥${formatMoney(remain)} 未分配,无法提交`);
return false;
}
if (!detailList.value.length) {
proxy?.$modal.msgWarning('请至少添加一条分款明细后再提交');
return false;
}
return true;
};
const formRemainingAmount = computed(() => { const formRemainingAmount = computed(() => {
const currentDetailAmount = Number(detailForm.detailAmount) || 0; const currentDetailAmount = Number(detailForm.detailAmount) || 0;
const existingTotal = Number( const existingTotal = Number(
@ -441,8 +442,7 @@ const handleAddDetail = () => {
proxy?.$modal.msgWarning('回款数据未加载'); proxy?.$modal.msgWarning('回款数据未加载');
return; return;
} }
if (!canAllocate.value) { if (!canEditDetail.value) {
proxy?.$modal.msgWarning(allocateHintText.value || '当前不可分款');
return; return;
} }
showProjectDialog.value = true; showProjectDialog.value = true;
@ -593,6 +593,9 @@ const handleApprovalRecord = () => {
}; };
const approvalVerifyOpen = async () => { const approvalVerifyOpen = async () => {
if (!validateAllocationBeforeSubmit()) {
return;
}
syncTaskVariables(); syncTaskVariables();
await submitVerifyRef.value?.openDialog(routeParams.value.taskId); await submitVerifyRef.value?.openDialog(routeParams.value.taskId);
}; };

@ -66,7 +66,7 @@
plain plain
icon="Promotion" icon="Promotion"
:disabled="!canDispatchSelection" :disabled="!canDispatchSelection"
@click="openDispatchDialog" @click="openDispatchDialog()"
v-hasPermi="['oa/erp:finAccountInstallment:dispatch']" v-hasPermi="['oa/erp:finAccountInstallment:dispatch']"
> >
派发客户经理 派发客户经理
@ -116,7 +116,7 @@
link link
type="warning" type="warning"
icon="Promotion" icon="Promotion"
@click.stop="handleDispatchRow(row)" @click.stop="openDispatchDialog([row])"
v-hasPermi="['oa/erp:finAccountInstallment:dispatch']" v-hasPermi="['oa/erp:finAccountInstallment:dispatch']"
/> />
</el-tooltip> </el-tooltip>
@ -266,7 +266,6 @@
> >
<template #description> <template #description>
<p class="detail-empty__desc">暂无分款明细</p> <p class="detail-empty__desc">暂无分款明细</p>
<p v-if="selectedInstallment.canAllocate" class="detail-empty__hint"></p>
</template> </template>
</el-empty> </el-empty>
</div> </div>
@ -387,7 +386,6 @@ import {
FinAccountInstallmentVO, FinAccountInstallmentVO,
FinAccountInstallmentDispatchForm FinAccountInstallmentDispatchForm
} from '@/api/oa/erp/finAccountInstallment/types'; } from '@/api/oa/erp/finAccountInstallment/types';
import { FlowCodeEnum } from '@/enums/OAEnum';
import { FinAccountInstallmentDetailVO } from '@/api/oa/erp/finAccountInstallmentDetail/types'; import { FinAccountInstallmentDetailVO } from '@/api/oa/erp/finAccountInstallmentDetail/types';
import { DArrowLeft } from '@element-plus/icons-vue'; import { DArrowLeft } from '@element-plus/icons-vue';
import { getUserList } from '@/api/system/user'; import { getUserList } from '@/api/system/user';
@ -519,47 +517,25 @@ const submitInstallmentForm = async () => {
} }
}; };
const openDispatchDialog = async () => { /** 打开派发弹窗(批量勾选或操作列单条) */
if (!canDispatchSelection.value) { const openDispatchDialog = async (rows?: FinAccountInstallmentVO[]) => {
proxy?.$modal.msgWarning('请勾选分款进度为「未分款」的回款'); const targetRows = rows ?? selectedInstallmentRows.value;
if (!targetRows.length || !targetRows.every(isNotAllocated)) {
proxy?.$modal.msgWarning(
rows?.length ? '仅未分款状态的回款可派发' : '请勾选分款进度为「未分款」的回款'
);
return; return;
} }
selectedInstallmentRows.value = targetRows;
dispatchManagerUserIds.value = []; dispatchManagerUserIds.value = [];
await loadManagerUserOptions(); await loadManagerUserOptions();
dispatchDialog.visible = true; dispatchDialog.visible = true;
}; };
/** 操作列:单条派发 */ const buildDispatchPayload = (): FinAccountInstallmentDispatchForm => ({
const handleDispatchRow = async (row: FinAccountInstallmentVO) => { accountInstallmentIds: selectedInstallmentRows.value.map((r) => r.accountInstallmentId),
if (!isNotAllocated(row)) { managerUserIds: dispatchManagerUserIds.value
proxy?.$modal.msgWarning('仅未分款状态的回款可派发'); });
return;
}
selectedInstallmentRows.value = [row];
dispatchManagerUserIds.value = [];
await loadManagerUserOptions();
dispatchDialog.visible = true;
};
/** 组装派发及流程启动参数(仿出差申请 submitAndFlowStart */
const buildDispatchPayload = (): FinAccountInstallmentDispatchForm => {
const accountManagerId = dispatchManagerUserIds.value.map((id) => String(id)).join(',');
const rows = selectedInstallmentRows.value;
return {
accountInstallmentIds: rows.map((r) => r.accountInstallmentId),
managerUserIds: dispatchManagerUserIds.value,
flowCode: FlowCodeEnum.FIN_ACCOUNT_INSTALLMENT_CODE,
variables: {
ignore: true,
accountManagerId
},
flowBizList: rows.map((row) => ({
businessId: String(row.accountInstallmentId),
businessCode: row.installmentCode,
businessTitle: `${row.customerName}分款审核`
}))
};
};
const submitDispatch = async () => { const submitDispatch = async () => {
if (!dispatchManagerUserIds.value.length) { if (!dispatchManagerUserIds.value.length) {
@ -641,17 +617,6 @@ const handleView = (row: FinAccountInstallmentVO) => {
}); });
}; };
/** 客户经理分款 */
const handleGoAllocate = (row: FinAccountInstallmentVO) => {
router.push({
path: '/oa/erp/finAccountInstallment/edit',
query: {
id: String(row.accountInstallmentId),
type: 'allocate'
}
});
};
const handleRowClick = async (row: FinAccountInstallmentVO) => { const handleRowClick = async (row: FinAccountInstallmentVO) => {
selectedInstallment.value = row; selectedInstallment.value = row;
await getDetailList(); await getDetailList();

Loading…
Cancel
Save