Compare commits

..

3 Commits

Author SHA1 Message Date
chenhao 5583bb0f11 feat(finance): 更新收款和开票审批功能
- 修改代理商为进货商的标签和提示文本
- 优化收款单表格列显示,添加预期收款金额和比例
- 实现预收和非预收单据的类型切换功能
- 添加应收单和订单表格的数据加载状态指示
- 更新应用付款对话框中的支付方式相关文本
- 增加收款金额与确认金额的一致性验证
- 完善应收单详情页面的字段展示和布局
- 添加发票详情类型字典配置
- 实现收款审批流程的审批历史和审批功能
- 创建收款单和退款单的审批相关路由
- 新增流程关联数据传输对象和相关配置
2025-12-29 15:31:27 +08:00
chenhao 47879d029a Merge branch 'refs/heads/master' into dev_1.0.0 2025-12-29 09:24:06 +08:00
chenhao 0b0add0b48 refactor(purchase): 优化采购订单查询的动态SQL逻辑
- 将原有的静态字段映射改为根据表名动态选择字段
- 使用choose/when替代if条件判断,提高SQL的可读性
- 重构了bu_todo和bu_todo_completed表的查询逻辑
- 移除了重复的approve_user条件过滤
- 优化了已完成任务表的聚合查询,使用max函数获取最新审批时间
2025-12-29 09:22:44 +08:00
49 changed files with 2339 additions and 396 deletions

View File

@ -88,3 +88,35 @@ export function applyRedRush(data) {
needLoading: true needLoading: true
}) })
} }
// 查询收款审批列表
export function listReceiptApprove(query) {
return request({
url: '/finance/receipt/approve/list',
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: query
})
}
// 查询已审批收款列表
export function listReceiptApproved(query) {
return request({
url: '/finance/receipt/approved/list',
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: query
})
}
// 查询收款单详细
export function getReceiptDetail(id) {
return request({
url: '/finance/receipt/' + id,
method: 'get'
})
}

View File

@ -39,7 +39,8 @@ export function mergeAndInitiateReceipt(data) {
return request({ return request({
url: '/finance/receivable/mergeAndInitiateReceipt', url: '/finance/receivable/mergeAndInitiateReceipt',
method: 'post', method: 'post',
data: data data: data,
needLoading:true
}) })
} }
@ -48,7 +49,8 @@ export function mergeAndInitiateInvoice(data) {
return request({ return request({
url: '/finance/receivable/mergeAndInitiateInvoice', url: '/finance/receivable/mergeAndInitiateInvoice',
method: 'post', method: 'post',
data: data data: data,
needLoading:true
}) })
} }

View File

@ -5,8 +5,11 @@ import {tansParams} from "@/utils/ruoyi"
export function listReceive(query) { export function listReceive(query) {
return request({ return request({
url: '/finance/receipt/list', url: '/finance/receipt/list',
method: 'get', method: 'post',
data: tansParams(query) headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: query
}) })
} }
@ -115,3 +118,13 @@ export function manualReceiptWriteOff(data) {
data: data data: data
}) })
} }
// 撤销收款单
export function revokeReceipt(id) {
return request({
url: '/finance/receipt/revoke',
method: 'post',
data: {id: id},
needLoading: true
})
}

View File

@ -109,6 +109,16 @@ export const constantRoutes = [
component: () => import('@/views/approve/finance/invoiceReceipt/approved/index'), component: () => import('@/views/approve/finance/invoiceReceipt/approved/index'),
hidden: true hidden: true
}, },
{
path: 'receiptLog',
component: () => import('@/views/approve/finance/receipt/approved/index.vue'),
hidden: true
},
{
path: 'receiptRefoundLog',
component: () => import('@/views/approve/finance/receiptRefound/approved/index.vue'),
hidden: true
},
] ]
}, },
{ {

View File

@ -0,0 +1,213 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
<el-form-item label="收款编号" prop="receiptBillCode">
<el-input v-model="queryParams.receiptBillCode" placeholder="请输入收款编号" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="进货商" prop="partnerName">
<el-input v-model="queryParams.partnerName" placeholder="请输入进货商" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="提交日期">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="receiptList">
<el-table-column label="序号" type="index" width="50" align="center" />
<el-table-column label="收款编号" align="center" prop="receiptBillCode" />
<el-table-column label="客户" align="center" prop="partnerName" />
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
<el-table-column label="金额" align="center" prop="totalPriceWithTax" />
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.applyTime) }}</span>
</template>
</el-table-column>
<el-table-column label="审批节点" align="center" prop="approveNode" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
<!-- 详情对话框 -->
<el-dialog title="收款单详情" :visible.sync="detailDialogVisible" width="80%" append-to-body>
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
<el-button
type="primary"
size="small"
icon="el-icon-download"
@click="exportPDF"
:loading="pdfExporting"
>导出PDF</el-button>
</div>
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
<ApproveLayout ref="approveLayout" title="收款单详情">
<receipt-detail :data="form"></receipt-detail>
<template #footer>
<span>收款编号: {{ form.receiptBillCode }}</span>
</template>
</ApproveLayout>
</div>
<el-divider content-position="left">流转意见</el-divider>
<div class="process-container">
<el-timeline>
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
<el-card>
<h4>{{ log.approveOpinion }}</h4>
<p><b>操作人:</b> {{ log.approveUserName }} </p>
<p><b>审批状态:</b> <el-tag size="small">{{ getStatusText(log.approveStatus) }}</el-tag></p>
</el-card>
</el-timeline-item>
</el-timeline>
<div v-if="!approveLogs || approveLogs.length === 0"></div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="detailDialogVisible = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { listReceiptApproved, getReceiptDetail } from "@/api/finance/receipt";
import { listCompletedFlows } from "@/api/flow";
import ReceiptDetail from "../components/ReceiptDetail";
import ApproveLayout from "@/views/approve/ApproveLayout";
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
export default {
name: "ReceiptApproved",
components: { ReceiptDetail, ApproveLayout },
data() {
return {
loading: true,
showSearch: true,
total: 0,
receiptList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
receiptBillCode: null,
partnerName: null,
projectName: null,
processKey: 'finance_receipt_approve',
},
dateRange: [],
detailDialogVisible: false,
detailLoading: false,
form: {},
approveLogs: [],
currentReceiptId: null,
pdfExporting: false
};
},
created() {
this.getList();
},
methods: {
getList() {
this.loading = true;
listReceiptApproved(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
this.receiptList = response.rows;
this.total = response.total;
this.loading = false;
});
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.dateRange = [];
this.resetForm("queryForm");
this.handleQuery();
},
handleView(row) {
this.form = {};
this.approveLogs = [];
this.currentReceiptId = row.id;
this.detailLoading = true;
this.detailDialogVisible = true;
getReceiptDetail(this.currentReceiptId).then(response => {
this.form = response.data;
this.loadApproveHistory(this.form.receiptBillCode);
this.detailLoading = false;
}).catch(() => {
this.detailLoading = false;
});
},
loadApproveHistory(businessKey) {
if (businessKey) {
listCompletedFlows({ businessKey: businessKey }).then(response => {
this.approveLogs = response.data;
});
}
},
getStatusText(status) {
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
return map[status] || '提交审批';
},
async exportPDF() {
this.pdfExporting = true;
try {
const element = this.$refs.approveLayout.$el;
const fileName = `收款单-${this.form.receiptBillCode || ''}.pdf`;
await exportElementToPDF(element, fileName);
this.$modal.msgSuccess('PDF导出成功');
} catch (error) {
console.error('PDF导出失败:', error);
this.$modal.msgError('PDF导出失败请稍后重试');
} finally {
this.pdfExporting = false;
}
}
}
};
</script>
<style scoped>
.process-container {
padding: 10px;
}
/* 导出PDF时的特殊样式 */
.approve-container.exporting-pdf ::v-deep .el-button--primary,
.approve-container.exporting-pdf ::v-deep .el-button--text {
display: none;
}
.approve-container.exporting-pdf ::v-deep .el-input__inner,
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
border: none !important;
box-shadow: none !important;
background-color: transparent !important;
resize: none !important;
padding: 0 !important;
}
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
display: none;
}
</style>

View File

@ -0,0 +1,133 @@
<template>
<div class="receipt-detail">
<el-descriptions title="收款单信息" :column="3" border>
<el-descriptions-item label="销售-收款单编号">{{ data.receiptBillCode }}</el-descriptions-item>
<el-descriptions-item :span="2" label="进货商名称">{{ data.partnerName }}</el-descriptions-item>
<!-- <el-descriptions-item label="收款单类型">-->
<!-- <dict-tag :options="dict.type.receipt_bill_type" :value="data.receiptBillType"/>-->
<!-- </el-descriptions-item>-->
<el-descriptions-item label="含税总价(元)">{{ data.totalPriceWithTax }}</el-descriptions-item>
<el-descriptions-item label="未税总价(元)">{{ data.totalPriceWithoutTax }}</el-descriptions-item>
<el-descriptions-item label="税额(元)">{{ data.taxAmount }}</el-descriptions-item>
<el-descriptions-item label="支付方式">
<dict-tag :options="dict.type.payment_method" :value="data.receiptMethod"/>
</el-descriptions-item>
<el-descriptions-item label="银行账号">{{ data.receiptBankNumber }}</el-descriptions-item>
<el-descriptions-item label="账户名称">{{ data.receiptAccountName }}</el-descriptions-item>
<el-descriptions-item label="银行开户行">{{ data.receiptBankOpenAddress }}</el-descriptions-item>
<el-descriptions-item label="银行行号">{{ data.bankNumber }}</el-descriptions-item>
<!-- <el-descriptions-item label="备注" :span="3">{{ data.remark }}</el-descriptions-item>-->
</el-descriptions>
<div class="section" style="margin-top: 20px;" v-show="data.detailDTOList && data.detailDTOList.length>0">
<div class="el-descriptions__title">应收单列表</div>
<el-table :data="data.detailDTOList" border style="width: 100%; margin-top: 10px;">
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
<el-table-column prop="receivableBillCode" label="销售-应收单编号" align="center"></el-table-column>
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
<el-table-column prop="productType" label="产品类型" align="center">
<template slot-scope="scope">
<dict-tag :options="dict.type.product_type" :value="scope.row.productType"/>
</template>
</el-table-column>
<el-table-column prop="totalPriceWithTax" label="含税总价" align="center"></el-table-column>
<el-table-column prop="receiptAmount" label="本次收款金额" align="center"></el-table-column>
</el-table>
</div>
<div class="section" style="margin-top: 20px;" v-if="attachments && attachments.length > 0">
<div class="el-descriptions__title">附件信息</div>
<el-table :data="attachments" border style="width: 100%; margin-top: 10px;">
<el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>
<el-table-column prop="createUserName" label="上传人" align="center"></el-table-column>
<el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreview(scope.row)"></el-button>
<el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog :visible.sync="pdfPreviewVisible" width="80%" append-to-body top="5vh" title="PDF预览">
<iframe :src="currentPdfUrl" width="100%" height="600px" frameborder="0"></iframe>
</el-dialog>
<el-dialog :visible.sync="imagePreviewVisible" width="60%" append-to-body top="5vh" title="图片预览">
<img :src="currentImageUrl" style="width: 100%;" />
</el-dialog>
</div>
</template>
<script>
import request from '@/utils/request';
export default {
name: "ReceiptDetail",
props: {
data: {
type: Object,
required: true,
default: () => ({})
}
},
dicts: ['receipt_bill_type', 'product_type','payment_method'],
data() {
return {
attachments: [],
pdfPreviewVisible: false,
currentPdfUrl: '',
imagePreviewVisible: false,
currentImageUrl: ''
};
},
watch: {
},
methods: {
isPdf(filePath) {
return filePath && filePath.toLowerCase().endsWith('.pdf');
},
getImageUrl(resource) {
return process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" + resource;
},
handlePreview(row) {
if (this.isPdf(row.filePath)) {
// PDF Preview logic
request({
url: '/common/download/resource',
method: 'get',
params: { resource: row.filePath },
responseType: 'blob'
}).then(res => {
const blob = new Blob([res.data], { type: 'application/pdf' });
this.currentPdfUrl = URL.createObjectURL(blob);
this.pdfPreviewVisible = true;
});
} else {
// Image Preview
this.currentImageUrl = this.getImageUrl(row.filePath);
this.imagePreviewVisible = true;
}
},
handleDownload(row) {
const link = document.createElement('a');
link.href = this.getImageUrl(row.filePath);
link.download = row.fileName || 'attachment';
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
};
</script>
<style scoped>
.receipt-detail {
margin-bottom: 20px;
}
</style>

View File

@ -0,0 +1,300 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
<el-form-item label="收款编号" prop="receiptBillCode">
<el-input v-model="queryParams.receiptBillCode" placeholder="请输入收款编号" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="进货商" prop="partnerName">
<el-input v-model="queryParams.partnerName" placeholder="请输入进货商名称" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="提交日期">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
size="mini"
@click="toApproved()"
>审批历史</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="receiptList">
<el-table-column label="序号" type="index" width="50" align="center" />
<el-table-column label="收款编号" align="center" prop="receiptBillCode" />
<el-table-column label="进货商" align="center" prop="partnerName" />
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
<el-table-column label="金额" align="center" prop="totalPriceWithTax" />
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="审批节点" align="center" prop="approveNode" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleApprove(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
<!-- 审批详情主对话框 -->
<el-dialog title="收款单审批" :visible.sync="detailDialogVisible" width="80%" append-to-body>
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
<el-button
type="primary"
size="small"
icon="el-icon-download"
@click="exportPDF"
:loading="pdfExporting"
>导出PDF</el-button>
</div>
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
<ApproveLayout ref="approveLayout" title="收款单详情">
<receipt-detail :data="form"></receipt-detail>
<template #footer>
<span>{{ form.receiptBillCode }}</span>
</template>
</ApproveLayout>
</div>
<el-divider content-position="left">流转意见</el-divider>
<div class="process-container">
<el-timeline>
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
<el-card>
<h4>{{ log.approveOpinion }}</h4>
<p><b>操作人:</b> {{ log.approveUserName }} </p>
<p><b>审批状态:</b> <el-tag size="small">{{ getStatusText(log.approveStatus) }}</el-tag></p>
</el-card>
</el-timeline-item>
</el-timeline>
<div v-if="!approveLogs || approveLogs.length === 0"></div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="openOpinionDialog('approve')"></el-button>
<el-button type="danger" @click="openOpinionDialog('reject')"></el-button>
<el-button @click="detailDialogVisible = false"> </el-button>
</span>
</el-dialog>
<!-- 审批意见对话框 -->
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
<el-form-item label="审批意见" prop="approveOpinion">
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="opinionDialogVisible = false"> </el-button>
<el-button type="primary" @click="showConfirmDialog()"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { listReceiptApprove, getReceiptDetail } from "@/api/finance/receipt";
import { approveTask, listCompletedFlows } from "@/api/flow";
import ReceiptDetail from "./components/ReceiptDetail";
import ApproveLayout from "@/views/approve/ApproveLayout";
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
export default {
name: "ReceiptApprove",
components: { ReceiptDetail, ApproveLayout },
data() {
return {
loading: true,
showSearch: true,
total: 0,
receiptList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
receiptBillCode: null,
partnerName: null,
projectName: null,
processKey: 'finance_receipt_approve',
},
dateRange: [],
detailDialogVisible: false,
detailLoading: false,
form: {},
approveLogs: [],
opinionDialogVisible: false,
confirmDialogTitle: '',
currentApproveType: '',
opinionForm: {
approveOpinion: ''
},
opinionRules: {
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
},
processKey: 'finance_receipt_approve',
taskId: null,
currentReceiptId: null,
pdfExporting: false
};
},
created() {
this.getList();
},
methods: {
getList() {
this.loading = true;
listReceiptApprove(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
this.receiptList = response.rows;
this.total = response.total;
this.loading = false;
});
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.dateRange = [];
this.resetForm("queryForm");
this.handleQuery();
},
toApproved() {
this.$router.push( '/approve/receiptLog' )
},
handleApprove(row) {
this.resetDetailForm();
this.currentReceiptId = row.id;
this.taskId = row.taskId;
this.detailLoading = true;
this.detailDialogVisible = true;
getReceiptDetail(this.currentReceiptId).then(response => {
this.form = response.data;
this.loadApproveHistory(this.form.receiptBillCode);
this.detailLoading = false;
}).catch(() => {
this.detailLoading = false;
});
},
resetDetailForm() {
this.form = {};
this.approveLogs = [];
this.opinionForm.approveOpinion = '';
},
loadApproveHistory(businessKey) {
if (businessKey) {
let keys = [];
if(this.processKey) keys.push(this.processKey);
listCompletedFlows({ businessKey: businessKey, processKeyList: keys }).then(response => {
this.approveLogs = response.data;
});
}
},
openOpinionDialog(type) {
this.currentApproveType = type;
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批';
this.opinionDialogVisible = true;
this.opinionForm.approveOpinion = '';
this.$nextTick(() => {
if(this.$refs.opinionForm) this.$refs.opinionForm.clearValidate();
});
},
showConfirmDialog() {
this.$refs.opinionForm.validate(valid => {
if (valid) {
this.opinionDialogVisible = false;
this.submitApproval();
}
});
},
submitApproval() {
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0;
const params = {
businessKey: this.form.receiptBillCode,
processKey: this.processKey,
taskId: this.taskId,
variables: {
comment: this.opinionForm.approveOpinion,
approveBtn: approveBtn
}
};
approveTask(params).then(() => {
this.$modal.msgSuccess(this.confirmDialogTitle + "成功");
this.detailDialogVisible = false;
this.getList();
});
},
getStatusText(status) {
if (!status) {
return '提交审批'
}
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
return map[status] || '提交审批';
},
async exportPDF() {
this.pdfExporting = true;
try {
const element = this.$refs.approveLayout.$el;
const fileName = `收款单-${this.form.receiptBillCode || ''}.pdf`;
await exportElementToPDF(element, fileName);
this.$modal.msgSuccess('PDF导出成功');
} catch (error) {
console.error('PDF导出失败:', error);
this.$modal.msgError('PDF导出失败请稍后重试');
} finally {
this.pdfExporting = false;
}
}
}
};
</script>
<style scoped>
.process-container {
padding: 10px;
}
/* 导出PDF时的特殊样式 */
.approve-container.exporting-pdf ::v-deep .el-button--primary,
.approve-container.exporting-pdf ::v-deep .el-button--text {
display: none;
}
.approve-container.exporting-pdf ::v-deep .el-input__inner,
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
border: none !important;
box-shadow: none !important;
background-color: transparent !important;
resize: none !important;
padding: 0 !important;
}
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
display: none;
}
</style>

View File

@ -0,0 +1,213 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
<el-form-item label="收款编号" prop="receiptBillCode">
<el-input v-model="queryParams.receiptBillCode" placeholder="请输入收款编号" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="进货商" prop="partnerName">
<el-input v-model="queryParams.partnerName" placeholder="请输入进货商" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="提交日期">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="receiptList">
<el-table-column label="序号" type="index" width="50" align="center" />
<el-table-column label="收款编号" align="center" prop="receiptBillCode" />
<el-table-column label="客户" align="center" prop="partnerName" />
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
<el-table-column label="金额" align="center" prop="totalPriceWithTax" />
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.applyTime) }}</span>
</template>
</el-table-column>
<el-table-column label="审批节点" align="center" prop="approveNode" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
<!-- 详情对话框 -->
<el-dialog title="收款单详情" :visible.sync="detailDialogVisible" width="80%" append-to-body>
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
<el-button
type="primary"
size="small"
icon="el-icon-download"
@click="exportPDF"
:loading="pdfExporting"
>导出PDF</el-button>
</div>
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
<ApproveLayout ref="approveLayout" title="收款单详情">
<receipt-detail :data="form"></receipt-detail>
<template #footer>
<span>收款编号: {{ form.receiptBillCode }}</span>
</template>
</ApproveLayout>
</div>
<el-divider content-position="left">流转意见</el-divider>
<div class="process-container">
<el-timeline>
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
<el-card>
<h4>{{ log.approveOpinion }}</h4>
<p><b>操作人:</b> {{ log.approveUserName }} </p>
<p><b>审批状态:</b> <el-tag size="small">{{ getStatusText(log.approveStatus) }}</el-tag></p>
</el-card>
</el-timeline-item>
</el-timeline>
<div v-if="!approveLogs || approveLogs.length === 0"></div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="detailDialogVisible = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { listReceiptApproved, getReceiptDetail } from "@/api/finance/receipt";
import { listCompletedFlows } from "@/api/flow";
import ReceiptDetail from "../components/ReceiptDetail";
import ApproveLayout from "@/views/approve/ApproveLayout";
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
export default {
name: "ReceiptRefoundApproved",
components: { ReceiptDetail, ApproveLayout },
data() {
return {
loading: true,
showSearch: true,
total: 0,
receiptList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
receiptBillCode: null,
partnerName: null,
projectName: null,
processKey: 'finance_receipt_refound',
},
dateRange: [],
detailDialogVisible: false,
detailLoading: false,
form: {},
approveLogs: [],
currentReceiptId: null,
pdfExporting: false
};
},
created() {
this.getList();
},
methods: {
getList() {
this.loading = true;
listReceiptApproved(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
this.receiptList = response.rows;
this.total = response.total;
this.loading = false;
});
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.dateRange = [];
this.resetForm("queryForm");
this.handleQuery();
},
handleView(row) {
this.form = {};
this.approveLogs = [];
this.currentReceiptId = row.id;
this.detailLoading = true;
this.detailDialogVisible = true;
getReceiptDetail(this.currentReceiptId).then(response => {
this.form = response.data;
this.loadApproveHistory(this.form.receiptBillCode);
this.detailLoading = false;
}).catch(() => {
this.detailLoading = false;
});
},
loadApproveHistory(businessKey) {
if (businessKey) {
listCompletedFlows({ businessKey: businessKey }).then(response => {
this.approveLogs = response.data;
});
}
},
getStatusText(status) {
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
return map[status] || '提交审批';
},
async exportPDF() {
this.pdfExporting = true;
try {
const element = this.$refs.approveLayout.$el;
const fileName = `收款单-${this.form.receiptBillCode || ''}.pdf`;
await exportElementToPDF(element, fileName);
this.$modal.msgSuccess('PDF导出成功');
} catch (error) {
console.error('PDF导出失败:', error);
this.$modal.msgError('PDF导出失败请稍后重试');
} finally {
this.pdfExporting = false;
}
}
}
};
</script>
<style scoped>
.process-container {
padding: 10px;
}
/* 导出PDF时的特殊样式 */
.approve-container.exporting-pdf ::v-deep .el-button--primary,
.approve-container.exporting-pdf ::v-deep .el-button--text {
display: none;
}
.approve-container.exporting-pdf ::v-deep .el-input__inner,
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
border: none !important;
box-shadow: none !important;
background-color: transparent !important;
resize: none !important;
padding: 0 !important;
}
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
display: none;
}
</style>

View File

@ -0,0 +1,133 @@
<template>
<div class="receipt-detail">
<el-descriptions title="收款单信息" :column="3" border>
<el-descriptions-item label="销售-收款单编号">{{ data.receiptBillCode }}</el-descriptions-item>
<el-descriptions-item :span="2" label="进货商名称">{{ data.partnerName }}</el-descriptions-item>
<!-- <el-descriptions-item label="收款单类型">-->
<!-- <dict-tag :options="dict.type.receipt_bill_type" :value="data.receiptBillType"/>-->
<!-- </el-descriptions-item>-->
<el-descriptions-item label="含税总价(元)">{{ data.totalPriceWithTax }}</el-descriptions-item>
<el-descriptions-item label="未税总价(元)">{{ data.totalPriceWithoutTax }}</el-descriptions-item>
<el-descriptions-item label="税额(元)">{{ data.taxAmount }}</el-descriptions-item>
<el-descriptions-item label="支付方式">
<dict-tag :options="dict.type.payment_method" :value="data.receiptMethod"/>
</el-descriptions-item>
<el-descriptions-item label="银行账号">{{ data.receiptBankNumber }}</el-descriptions-item>
<el-descriptions-item label="账户名称">{{ data.receiptAccountName }}</el-descriptions-item>
<el-descriptions-item label="银行开户行">{{ data.receiptBankOpenAddress }}</el-descriptions-item>
<el-descriptions-item label="银行行号">{{ data.bankNumber }}</el-descriptions-item>
<!-- <el-descriptions-item label="备注" :span="3">{{ data.remark }}</el-descriptions-item>-->
</el-descriptions>
<div class="section" style="margin-top: 20px;" v-show="data.detailDTOList && data.detailDTOList.length>0">
<div class="el-descriptions__title">应收单列表</div>
<el-table :data="data.detailDTOList" border style="width: 100%; margin-top: 10px;">
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
<el-table-column prop="receivableBillCode" label="销售-应收单编号" align="center"></el-table-column>
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
<el-table-column prop="productType" label="产品类型" align="center">
<template slot-scope="scope">
<dict-tag :options="dict.type.product_type" :value="scope.row.productType"/>
</template>
</el-table-column>
<el-table-column prop="totalPriceWithTax" label="含税总价" align="center"></el-table-column>
<el-table-column prop="receiptAmount" label="本次收款金额" align="center"></el-table-column>
</el-table>
</div>
<div class="section" style="margin-top: 20px;" v-if="attachments && attachments.length > 0">
<div class="el-descriptions__title">附件信息</div>
<el-table :data="attachments" border style="width: 100%; margin-top: 10px;">
<el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>
<el-table-column prop="createUserName" label="上传人" align="center"></el-table-column>
<el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreview(scope.row)"></el-button>
<el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog :visible.sync="pdfPreviewVisible" width="80%" append-to-body top="5vh" title="PDF预览">
<iframe :src="currentPdfUrl" width="100%" height="600px" frameborder="0"></iframe>
</el-dialog>
<el-dialog :visible.sync="imagePreviewVisible" width="60%" append-to-body top="5vh" title="图片预览">
<img :src="currentImageUrl" style="width: 100%;" />
</el-dialog>
</div>
</template>
<script>
import request from '@/utils/request';
export default {
name: "ReceiptRefoundDetail",
props: {
data: {
type: Object,
required: true,
default: () => ({})
}
},
dicts: ['receipt_bill_type', 'product_type','payment_method'],
data() {
return {
attachments: [],
pdfPreviewVisible: false,
currentPdfUrl: '',
imagePreviewVisible: false,
currentImageUrl: ''
};
},
watch: {
},
methods: {
isPdf(filePath) {
return filePath && filePath.toLowerCase().endsWith('.pdf');
},
getImageUrl(resource) {
return process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" + resource;
},
handlePreview(row) {
if (this.isPdf(row.filePath)) {
// PDF Preview logic
request({
url: '/common/download/resource',
method: 'get',
params: { resource: row.filePath },
responseType: 'blob'
}).then(res => {
const blob = new Blob([res.data], { type: 'application/pdf' });
this.currentPdfUrl = URL.createObjectURL(blob);
this.pdfPreviewVisible = true;
});
} else {
// Image Preview
this.currentImageUrl = this.getImageUrl(row.filePath);
this.imagePreviewVisible = true;
}
},
handleDownload(row) {
const link = document.createElement('a');
link.href = this.getImageUrl(row.filePath);
link.download = row.fileName || 'attachment';
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
};
</script>
<style scoped>
.receipt-detail {
margin-bottom: 20px;
}
</style>

View File

@ -0,0 +1,300 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
<el-form-item label="收款编号" prop="receiptBillCode">
<el-input v-model="queryParams.receiptBillCode" placeholder="请输入收款编号" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="进货商" prop="partnerName">
<el-input v-model="queryParams.partnerName" placeholder="请输入进货商名称" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="提交日期">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
size="mini"
@click="toApproved()"
>审批历史</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="receiptList">
<el-table-column label="序号" type="index" width="50" align="center" />
<el-table-column label="收款编号" align="center" prop="receiptBillCode" />
<el-table-column label="进货商" align="center" prop="partnerName" />
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
<el-table-column label="金额" align="center" prop="totalPriceWithTax" />
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="审批节点" align="center" prop="approveNode" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleApprove(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
<!-- 审批详情主对话框 -->
<el-dialog title="收款单审批" :visible.sync="detailDialogVisible" width="80%" append-to-body>
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
<el-button
type="primary"
size="small"
icon="el-icon-download"
@click="exportPDF"
:loading="pdfExporting"
>导出PDF</el-button>
</div>
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
<ApproveLayout ref="approveLayout" title="收款单详情">
<receipt-detail :data="form"></receipt-detail>
<template #footer>
<span>{{ form.receiptBillCode }}</span>
</template>
</ApproveLayout>
</div>
<el-divider content-position="left">流转意见</el-divider>
<div class="process-container">
<el-timeline>
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
<el-card>
<h4>{{ log.approveOpinion }}</h4>
<p><b>操作人:</b> {{ log.approveUserName }} </p>
<p><b>审批状态:</b> <el-tag size="small">{{ getStatusText(log.approveStatus) }}</el-tag></p>
</el-card>
</el-timeline-item>
</el-timeline>
<div v-if="!approveLogs || approveLogs.length === 0"></div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="openOpinionDialog('approve')"></el-button>
<el-button type="danger" @click="openOpinionDialog('reject')"></el-button>
<el-button @click="detailDialogVisible = false"> </el-button>
</span>
</el-dialog>
<!-- 审批意见对话框 -->
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
<el-form-item label="审批意见" prop="approveOpinion">
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="opinionDialogVisible = false"> </el-button>
<el-button type="primary" @click="showConfirmDialog()"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { listReceiptApprove, getReceiptDetail } from "@/api/finance/receipt";
import { approveTask, listCompletedFlows } from "@/api/flow";
import ReceiptDetail from "./components/ReceiptDetail";
import ApproveLayout from "@/views/approve/ApproveLayout";
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
export default {
name: "ReceiptRefoundApprove",
components: { ReceiptDetail, ApproveLayout },
data() {
return {
loading: true,
showSearch: true,
total: 0,
receiptList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
receiptBillCode: null,
partnerName: null,
projectName: null,
processKey: 'finance_receipt_refound',
},
dateRange: [],
detailDialogVisible: false,
detailLoading: false,
form: {},
approveLogs: [],
opinionDialogVisible: false,
confirmDialogTitle: '',
currentApproveType: '',
opinionForm: {
approveOpinion: ''
},
opinionRules: {
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
},
processKey: 'finance_receipt_refound',
taskId: null,
currentReceiptId: null,
pdfExporting: false
};
},
created() {
this.getList();
},
methods: {
getList() {
this.loading = true;
listReceiptApprove(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
this.receiptList = response.rows;
this.total = response.total;
this.loading = false;
});
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.dateRange = [];
this.resetForm("queryForm");
this.handleQuery();
},
toApproved() {
this.$router.push( '/approve/receiptRefoundLog' )
},
handleApprove(row) {
this.resetDetailForm();
this.currentReceiptId = row.id;
this.taskId = row.taskId;
this.detailLoading = true;
this.detailDialogVisible = true;
getReceiptDetail(this.currentReceiptId).then(response => {
this.form = response.data;
this.loadApproveHistory(this.form.receiptBillCode);
this.detailLoading = false;
}).catch(() => {
this.detailLoading = false;
});
},
resetDetailForm() {
this.form = {};
this.approveLogs = [];
this.opinionForm.approveOpinion = '';
},
loadApproveHistory(businessKey) {
if (businessKey) {
let keys = [];
if(this.processKey) keys.push(this.processKey);
listCompletedFlows({ businessKey: businessKey, processKeyList: keys }).then(response => {
this.approveLogs = response.data;
});
}
},
openOpinionDialog(type) {
this.currentApproveType = type;
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批';
this.opinionDialogVisible = true;
this.opinionForm.approveOpinion = '';
this.$nextTick(() => {
if(this.$refs.opinionForm) this.$refs.opinionForm.clearValidate();
});
},
showConfirmDialog() {
this.$refs.opinionForm.validate(valid => {
if (valid) {
this.opinionDialogVisible = false;
this.submitApproval();
}
});
},
submitApproval() {
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0;
const params = {
businessKey: this.form.receiptBillCode,
processKey: this.processKey,
taskId: this.taskId,
variables: {
comment: this.opinionForm.approveOpinion,
approveBtn: approveBtn
}
};
approveTask(params).then(() => {
this.$modal.msgSuccess(this.confirmDialogTitle + "成功");
this.detailDialogVisible = false;
this.getList();
});
},
getStatusText(status) {
if (!status) {
return '提交审批'
}
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
return map[status] || '提交审批';
},
async exportPDF() {
this.pdfExporting = true;
try {
const element = this.$refs.approveLayout.$el;
const fileName = `收款单-${this.form.receiptBillCode || ''}.pdf`;
await exportElementToPDF(element, fileName);
this.$modal.msgSuccess('PDF导出成功');
} catch (error) {
console.error('PDF导出失败:', error);
this.$modal.msgError('PDF导出失败请稍后重试');
} finally {
this.pdfExporting = false;
}
}
}
};
</script>
<style scoped>
.process-container {
padding: 10px;
}
/* 导出PDF时的特殊样式 */
.approve-container.exporting-pdf ::v-deep .el-button--primary,
.approve-container.exporting-pdf ::v-deep .el-button--text {
display: none;
}
.approve-container.exporting-pdf ::v-deep .el-input__inner,
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
border: none !important;
box-shadow: none !important;
background-color: transparent !important;
resize: none !important;
padding: 0 !important;
}
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
display: none;
}
</style>

View File

@ -7,45 +7,47 @@
<div class="details-container"> <div class="details-container">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
<div class="detail-item"><strong>应收单编号:</strong> {{ formData.receivableBillCode }}</div> <div class="detail-item"><strong>项目编号:</strong> {{ formData.projectCode }}</div>
</el-col> </el-col>
<el-col :span="8">
<div class="detail-item"><strong>项目名称:</strong> {{ formData.projectName }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>销售-应收单编号:</strong> {{ formData.receivableBillCode }}</div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="16"> <el-col :span="16">
<div class="detail-item"><strong>生成时间:</strong> {{ formData.createTime }}</div> <div class="detail-item"><strong>生成时间:</strong> {{ formData.createTime }}</div>
</el-col> </el-col>
<el-col :span="8">
<div class="detail-item"><strong>该进货商是否有预收单:</strong> {{ formData.remainingAmount == 0 ? '否' : '是' }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>预收金额:</strong> {{ formData.remainingAmount }}</div>
</el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
<div class="detail-item"><strong>进货商名称:</strong> {{ formData.partnerName }}</div> <div class="detail-item"><strong>进货商名称:</strong> {{ formData.partnerName }}</div>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<div class="detail-item"><strong>项目编号:</strong> {{ formData.projectCode }}</div> <div class="detail-item"><strong>订单编号:</strong> {{ formData.orderCode }}</div>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<div class="detail-item"><strong>项目名称:</strong> {{ formData.projectName }}</div> <div class="detail-item"><strong>出库单号:</strong> {{ formData.inventoryCode }}</div>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
<div class="detail-item"><strong>合同编号:</strong> {{ formData.orderCode }}</div> <div class="detail-item"><strong>含税总价():</strong> {{ formData.totalPriceWithTax }}</div>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<div class="detail-item"><strong>出入库单号:</strong> {{ formData.inventoryCode }}</div> <div class="detail-item"><strong>未税总价():</strong> {{ formData.totalPriceWithoutTax }}</div>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<div class="detail-item" style="display: flex"><strong>产品类型:</strong> <div class="detail-item"><strong>税额():</strong> {{ formData.taxAmount }}</div>
<dict-tag :options="dict.type.product_type" :value="formData.productType"/>
</div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<div class="detail-item"><strong>含税总价:</strong> {{ formData.totalPriceWithTax }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>未税总价:</strong> {{ formData.totalPriceWithoutTax }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>税额:</strong> {{ formData.taxAmount }}</div>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
@ -70,6 +72,19 @@
<div class="detail-item"><strong>开票中金额:</strong> {{ this.$calc.sub(this.$calc.sub(formData.totalPriceWithTax,formData.invoicedAmount),formData.uninvoicedAmount)}}</div> <div class="detail-item"><strong>开票中金额:</strong> {{ this.$calc.sub(this.$calc.sub(formData.totalPriceWithTax,formData.invoicedAmount),formData.uninvoicedAmount)}}</div>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20">
<el-col :span="8">
<div class="detail-item"><strong>生成收款单:</strong> {{ formData.totalPriceWithTax==formData.unreceivedAmount ? '未生成' : formData.unreceivedAmount == 0 ? '已生成' : '部分生成'}}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>生成开票单:</strong> {{ formData.totalPriceWithTax==formData.uninvoicedAmount ? '未生成' : formData.uninvoicedAmount == 0 ? '已生成' : '部分生成'}}</div>
</el-col>
<el-col :span="8">
<div class="detail-item" style="display: flex"><strong>产品类型:</strong>
<dict-tag :options="dict.type.product_type" :value="formData.productType"/>
</div>
</el-col>
</el-row>
</div> </div>
</div> </div>
@ -77,7 +92,7 @@
<div style="padding: 20px"> <div style="padding: 20px">
<el-tabs v-model="activeTab"> <el-tabs v-model="activeTab">
<el-tab-pane label="明细" name="details"> <el-tab-pane label="明细" name="details">
<el-divider content-position="left">销售收款单</el-divider> <el-divider content-position="left">销售-收款单</el-divider>
<el-table :data="formData.detailList" style="width: 100%" show-summary :summary-method="getSummaries"> <el-table :data="formData.detailList" style="width: 100%" show-summary :summary-method="getSummaries">
<el-table-column type="index" label="序号" width="50"></el-table-column> <el-table-column type="index" label="序号" width="50"></el-table-column>
<el-table-column prop="receivableDetailType" label="收款通道"> <el-table-column prop="receivableDetailType" label="收款通道">
@ -97,7 +112,7 @@
<dict-tag :options="dict.type.receipt_bill_status" :value="scope.row.receiptStatus"/> <dict-tag :options="dict.type.receipt_bill_status" :value="scope.row.receiptStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="receiptBillCode" label="销售收款单编号"></el-table-column> <el-table-column prop="receiptBillCode" label="销售-收款单编号"></el-table-column>
<el-table-column label="回执单/退款图"> <el-table-column label="回执单/退款图">
<template slot-scope="scope"> <template slot-scope="scope">
<span v-if="scope.row.finAttachment"> <span v-if="scope.row.finAttachment">
@ -109,14 +124,14 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-divider content-position="left">销售开票单</el-divider> <el-divider content-position="left">销售-开票单</el-divider>
<el-table :data="formData.invoiceDetailList" style="width: 100%" show-summary :summary-method="getInvoiceSummaries"> <el-table :data="formData.invoiceDetailList" style="width: 100%" show-summary :summary-method="getInvoiceSummaries">
<el-table-column type="index" label="序号" width="50"></el-table-column> <el-table-column type="index" label="序号" width="50"></el-table-column>
<!-- <el-table-column prop="receivableDetailType" label="开票通道">--> <el-table-column prop="receivableDetailType" label="开票通道">
<!-- <template slot-scope="scope">--> <template slot-scope="scope">
<!-- <dict-tag :options="dict.type.receivable_detail_type" :value="scope.row.receivableDetailType"/>--> <dict-tag :options="dict.type.invoice_detail_type" :value="scope.row.receivableDetailType"/>
<!-- </template>--> </template>
<!-- </el-table-column>--> </el-table-column>
<el-table-column prop="actualInvoiceTime" label="实际开票时间"> <el-table-column prop="actualInvoiceTime" label="实际开票时间">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.actualInvoiceTime || '-' }} {{ scope.row.actualInvoiceTime || '-' }}
@ -129,8 +144,8 @@
<dict-tag :options="dict.type.invoice_bill_status" :value="scope.row.invoiceStatus"/> <dict-tag :options="dict.type.invoice_bill_status" :value="scope.row.invoiceStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="invoiceBillCode" label="销售开票单编号"></el-table-column> <el-table-column prop="invoiceBillCode" label="销售-开票单编号"></el-table-column>
<el-table-column label="回执单/退款图"> <el-table-column label="发票/红冲发票">
<template slot-scope="scope"> <template slot-scope="scope">
<span v-if="scope.row.attachment"> <span v-if="scope.row.attachment">
<el-button type="text" size="mini" icon="el-icon-view" @click="handlePreview(scope.row.attachment)"></el-button> <el-button type="text" size="mini" icon="el-icon-view" @click="handlePreview(scope.row.attachment)"></el-button>
@ -168,7 +183,7 @@ import GlobalFilePreview from "@/components/GlobalFilePreview/index.vue";
export default { export default {
name: "EditForm", name: "EditForm",
dicts: ['product_type','receipt_bill_status','receivable_detail_type', 'invoice_bill_status'], dicts: ['product_type','receipt_bill_status','receivable_detail_type', 'invoice_bill_status','invoice_detail_type'],
components: { components: {
GlobalFilePreview, GlobalFilePreview,
ReceiptPlan, ReceiptPlan,

View File

@ -15,7 +15,7 @@
<el-table-column label="序号" type="index" width="50" align="center"></el-table-column> <el-table-column label="序号" type="index" width="50" align="center"></el-table-column>
<el-table-column label="预计开票时间" align="center" width="200"> <el-table-column label="预计开票时间" align="center" width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<el-date-picker v-model="scope.row.planInvoiceDate" type="date" style="width: 180px" <el-date-picker v-model="scope.row.planInvoiceDate" type="datetime" style="width: 180px"
value-format="yyyy-MM-dd HH:mm:ss" value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期" placeholder="选择日期"
:disabled="!isEditing || isNumberStr(scope.row.detailId)"></el-date-picker> :disabled="!isEditing || isNumberStr(scope.row.detailId)"></el-date-picker>

View File

@ -3,44 +3,55 @@
<div class="dialog-body"> <div class="dialog-body">
<el-form ref="form" :model="form" :inline="true" label-width="120px"> <el-form ref="form" :model="form" :inline="true" label-width="120px">
<el-row> <el-row>
<el-col :span="8"> <!-- <el-col :span="8">-->
<el-form-item label="开票单类型" prop="invoiceBillType"> <!-- <el-form-item label="开票单类型" prop="invoiceBillType">-->
<el-select disabled v-model="form.invoiceBillType" placeholder="请选择开票单类型" clearable> <!-- <el-select disabled v-model="form.invoiceBillType" placeholder="请选择开票单类型" clearable>-->
<el-option <!-- <el-option-->
v-for="dict in dict.type.receipt_bill_type" <!-- v-for="dict in dict.type.receipt_bill_type"-->
:key="dict.value" <!-- :key="dict.value"-->
:label="dict.label" <!-- :label="dict.label"-->
:value="dict.value" <!-- :value="dict.value"-->
/> <!-- />-->
</el-select> <!-- </el-select>-->
</el-form-item> <!-- </el-form-item>-->
</el-col> <!-- </el-col>-->
<el-col :span="8"> <el-col :span="8">
<el-form-item label="进货商名称"> <el-form-item label="进货商名称">
<el-input v-model="form.partnerName" readonly/> <el-input v-model="form.partnerName" readonly/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <!-- <el-col :span="8">-->
<el-form-item label="预计开票时间" prop="invoiceTime"> <!-- <el-form-item label="预计开票时间" prop="invoiceTime">-->
<el-date-picker <!-- <el-date-picker-->
v-model="form.invoiceTime" <!-- v-model="form.invoiceTime"-->
type="date" <!-- type="date"-->
value-format="yyyy-MM-dd HH:mm:ss" <!-- value-format="yyyy-MM-dd HH:mm:ss"-->
placeholder="选择日期" <!-- placeholder="选择日期"-->
></el-date-picker> <!-- ></el-date-picker>-->
</el-form-item> <!-- </el-form-item>-->
</el-col> <!-- </el-col>-->
</el-row> </el-row>
</el-form> </el-form>
<el-divider content-position="left">销售应收单表</el-divider> <el-divider content-position="left">销售-应收单表</el-divider>
<el-table :data="receivableBillsWithPlans" border max-height="300px" style="margin-bottom: 20px;"> <el-table :data="receivableBillsWithPlans" border max-height="300px" style="margin-bottom: 20px;">
<el-table-column label="应收单编号" align="center" prop="receivableBillCode" width="150"/> <el-table-column label="销售-应收单编号" align="center" prop="receivableBillCode" width="150"/>
<el-table-column label="预计开票时间" align="center" prop="planInvoiceDate" width="180"/> <el-table-column label="预计开票时间" align="center" prop="planInvoiceDate" width="180"/>
<el-table-column label="开票计划" align="center" width="100" prop="planInvoiceAmount"> <!-- <el-table-column label="开票计划" align="center" width="100" prop="planInvoiceAmount">-->
<!-- </el-table-column>-->
<el-table-column label="预期开票金额" align="center" width="120">
<template slot-scope="scope">
{{ calculateOrderCurrentInvoiceAmount(scope.row.id).toFixed(2) }}
</template>
</el-table-column> </el-table-column>
<el-table-column label="合同编号" align="center" prop="orderCode" width="150"/> <el-table-column label="预期开票比例" align="center" width="120">
<el-table-column label="出入库单号" align="center" prop="inventoryCode" width="150"/> <template slot-scope="scope">
{{ calculateOrderCurrentInvoiceRate(scope.row.id) }}%
</template>
</el-table-column>
<el-table-column label="项目名称" align="center" prop="projectName" width="150"/>
<el-table-column label="进货商名称" align="center" prop="partnerName" width="150"/>
<!-- <el-table-column label="出入库单号" align="center" prop="inventoryCode" width="150"/>-->
<!-- <el-table-column label="开票状态" align="center" prop="invoiceStatus" width="120"> <!-- <el-table-column label="开票状态" align="center" prop="invoiceStatus" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.invoice_status" :value="scope.row.invoiceStatus"/> <dict-tag :options="dict.type.invoice_status" :value="scope.row.invoiceStatus"/>
@ -48,17 +59,13 @@
</el-table-column> --> </el-table-column> -->
<el-table-column label="含税总价" align="center" prop="totalPriceWithTax" width="120"/> <el-table-column label="含税总价" align="center" prop="totalPriceWithTax" width="120"/>
<el-table-column label="未开票金额" align="center" prop="uninvoicedAmount" width="120"/> <el-table-column label="未开票金额" align="center" prop="uninvoicedAmount" width="120"/>
<el-table-column label="本次开票金额" align="center" width="120">
<template slot-scope="scope">
{{ calculateOrderCurrentInvoiceAmount(scope.row.id).toFixed(2) }}
</template>
</el-table-column>
<el-table-column label="本次开票比例" align="center" width="120">
<template slot-scope="scope">
{{ calculateOrderCurrentInvoiceRate(scope.row.id) }}%
</template>
</el-table-column>
<el-table-column label="已开票金额" align="center" prop="invoicedAmount" width="120"/> <el-table-column label="已开票金额" align="center" prop="invoicedAmount" width="120"/>
<el-table-column label="开票中金额" align="center" prop="invoicedAmount" width="120">
<template slot-scope="scope">
{{ $calc.sub($calc.sub(scope.row.totalPriceWithTax, scope.row.invoicedAmount), scope.row.uninvoicedAmount) }}
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100" fixed="right"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
@ -233,14 +240,14 @@ export default {
}, },
handleConfirm() { handleConfirm() {
// Validate main form fields // Validate main form fields
if (!this.form.invoiceBillType) { // if (!this.form.invoiceBillType) {
this.$modal.msgError('请选择开票单类型'); // this.$modal.msgError('');
return; // return;
} // }
if (!this.form.invoiceTime) { // if (!this.form.invoiceTime) {
this.$modal.msgError('请选择预计开票时间'); // this.$modal.msgError('');
return; // return;
} // }
// Validate each receivable order's invoice plans // Validate each receivable order's invoice plans
for (const order of this.receivableBillsWithPlans) { for (const order of this.receivableBillsWithPlans) {

View File

@ -3,63 +3,69 @@
<div class="dialog-body"> <div class="dialog-body">
<el-form ref="form" :model="form" :inline="true" label-width="120px"> <el-form ref="form" :model="form" :inline="true" label-width="120px">
<el-row> <el-row>
<el-col :span="8"> <!-- <el-col :span="8">-->
<el-form-item label="收款单类型" prop="receiptBillType"> <!-- <el-form-item label="收款单类型" prop="receiptBillType">-->
<el-select disabled v-model="form.receiptBillType" placeholder="请选择收款单类型" clearable> <!-- <el-select disabled v-model="form.receiptBillType" placeholder="请选择收款单类型" clearable>-->
<el-option <!-- <el-option-->
v-for="dict in dict.type.receipt_bill_type" <!-- v-for="dict in dict.type.receipt_bill_type"-->
:key="dict.value" <!-- :key="dict.value"-->
:label="dict.label" <!-- :label="dict.label"-->
:value="dict.value" <!-- :value="dict.value"-->
/> <!-- />-->
</el-select> <!-- </el-select>-->
</el-form-item> <!-- </el-form-item>-->
</el-col> <!-- </el-col>-->
<el-col :span="8"> <el-col :span="8">
<el-form-item label="进货商名称"> <el-form-item label="进货商名称">
<el-input v-model="form.partnerName" readonly/> <el-input v-model="form.partnerName" readonly/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <!-- <el-col :span="8">-->
<el-form-item label="预计收款时间" prop="estimatedReceiptTime"> <!-- <el-form-item label="预计收款时间" prop="estimatedReceiptTime">-->
<el-date-picker <!-- <el-date-picker-->
v-model="form.estimatedReceiptTime" <!-- v-model="form.estimatedReceiptTime"-->
type="date" <!-- type="date"-->
value-format="yyyy-MM-dd HH:mm:ss" <!-- value-format="yyyy-MM-dd HH:mm:ss"-->
placeholder="选择日期" <!-- placeholder="选择日期"-->
></el-date-picker> <!-- ></el-date-picker>-->
</el-form-item> <!-- </el-form-item>-->
</el-col> <!-- </el-col>-->
</el-row> </el-row>
</el-form> </el-form>
<el-divider content-position="left">销售应收单表</el-divider> <el-divider content-position="left">销售-应收单表</el-divider>
<el-table :data="receivableBillsWithPlans" border max-height="300px" style="margin-bottom: 20px;"> <el-table :data="receivableBillsWithPlans" border max-height="300px" style="margin-bottom: 20px;">
<el-table-column label="应收单编号" align="center" prop="receivableBillCode" width="150"/> <el-table-column label="销售-应收单编号" align="center" prop="receivableBillCode" width="150"/>
<el-table-column label="预计收款时间" align="center" prop="planReceiptDate" width="180"/> <el-table-column label="预计收款时间" align="center" prop="planReceiptDate" width="180"/>
<el-table-column label="收款计划" align="center" width="100" prop="planAmount"> <!-- <el-table-column label="收款计划" align="center" width="100" prop="planAmount">-->
<!-- </el-table-column>-->
<el-table-column label="预期收款金额" align="center" width="120">
<template slot-scope="scope">
{{ calculateOrderCurrentReceiptAmount(scope.row.id).toFixed(2) }}
</template>
</el-table-column> </el-table-column>
<!-- <el-table-column label="项目名称" align="center" prop="projectName" width="150"/> --> <el-table-column label="预期收款比例" align="center" width="120">
<el-table-column label="合同编号" align="center" prop="orderCode" width="150"/> <template slot-scope="scope">
<el-table-column label="出入库单号" align="center" prop="inventoryCode" width="150"/> {{ calculateOrderCurrentReceiptRate(scope.row.id) }}
</template>
</el-table-column>
<el-table-column label="项目名称" align="center" prop="projectName" width="150"/>
<el-table-column label="进货商名称" align="center" prop="partnerName" width="150"/>
<!-- <el-table-column label="出入库单号" align="center" prop="inventoryCode" width="150"/>-->
<!-- <el-table-column label="收款状态" align="center" prop="collectionStatus" width="120"> <!-- <el-table-column label="收款状态" align="center" prop="collectionStatus" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.collection_status" :value="scope.row.collectionStatus"/> <dict-tag :options="dict.type.collection_status" :value="scope.row.collectionStatus"/>
</template> </template>
</el-table-column> --> </el-table-column> -->
<el-table-column label="含税总价" align="center" prop="totalPriceWithTax" width="120"/> <el-table-column label="含税总价(元)" align="center" prop="totalPriceWithTax" width="120"/>
<el-table-column label="未收款金额" align="center" prop="unreceivedAmount" width="120"/> <el-table-column label="未收款金额(元)" align="center" prop="unreceivedAmount" width="120"/>
<el-table-column label="本次收款金额" align="center" width="120"> <el-table-column label="已收款金额(元)" align="center" prop="receivedAmount" width="120"/>
<el-table-column label="收款中金额(元)" align="center" prop="receivedAmount" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
{{ calculateOrderCurrentReceiptAmount(scope.row.id).toFixed(2) }} {{ $calc.sub($calc.sub(scope.row.totalPriceWithTax, scope.row.receivedAmount), scope.row.unreceivedAmount) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="本次收款比例" align="center" width="120">
<template slot-scope="scope">
{{ calculateOrderCurrentReceiptRate(scope.row.id) }}%
</template>
</el-table-column>
<el-table-column label="已收款金额" align="center" prop="receivedAmount" width="120"/>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100" fixed="right"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
@ -232,14 +238,14 @@ export default {
}, },
handleConfirm() { handleConfirm() {
// Validate main form fields // Validate main form fields
if (!this.form.receiptBillType) { // if (!this.form.receiptBillType) {
this.$modal.msgError('请选择收款单类型'); // this.$modal.msgError('');
return; // return;
} // }
if (!this.form.estimatedReceiptTime) { // if (!this.form.estimatedReceiptTime) {
this.$modal.msgError('请选择预计收款时间'); // this.$modal.msgError('');
return; // return;
} // }
// Validate each receivable order's receipt plans // Validate each receivable order's receipt plans
for (const order of this.receivableBillsWithPlans) { for (const order of this.receivableBillsWithPlans) {

View File

@ -19,7 +19,7 @@
<el-table-column label="序号" type="index" width="50" align="center"></el-table-column> <el-table-column label="序号" type="index" width="50" align="center"></el-table-column>
<el-table-column label="预计收款时间" align="center" width="200"> <el-table-column label="预计收款时间" align="center" width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<el-date-picker v-model="scope.row.planReceiptDate" type="date" style="width: 180px" <el-date-picker v-model="scope.row.planReceiptDate" type="datetime" style="width: 180px"
value-format="yyyy-MM-dd HH:mm:ss" value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期" placeholder="选择日期"
:disabled="!isEditing || isNumberStr(scope.row.detailId)"></el-date-picker> :disabled="!isEditing || isNumberStr(scope.row.detailId)"></el-date-picker>

View File

@ -1,14 +1,14 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="150px">
<el-form-item label="项目编号" prop="projectCode"> <!-- <el-form-item label="项目编号" prop="projectCode">-->
<el-input <!-- <el-input-->
v-model="queryParams.projectCode" <!-- v-model="queryParams.projectCode"-->
placeholder="请输入项目编号" <!-- placeholder="请输入项目编号"-->
clearable <!-- clearable-->
@keyup.enter.native="handleQuery" <!-- @keyup.enter.native="handleQuery"-->
/> <!-- />-->
</el-form-item> <!-- </el-form-item>-->
<el-form-item label="项目名称" prop="projectName"> <el-form-item label="项目名称" prop="projectName">
<el-input <el-input
v-model="queryParams.projectName" v-model="queryParams.projectName"
@ -17,7 +17,7 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="应收单编号" prop="receivableBillCode"> <el-form-item label="销售-应收单编号" prop="receivableBillCode">
<el-input <el-input
v-model="queryParams.receivableBillCode" v-model="queryParams.receivableBillCode"
placeholder="请输入应收单编号" placeholder="请输入应收单编号"
@ -25,9 +25,9 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="客户名称" prop="customerName"> <el-form-item label="进货商名称" prop="partnerName">
<el-input <el-input
v-model="queryParams.customerName" v-model="queryParams.partnerName"
placeholder="请输入客户名称" placeholder="请输入客户名称"
clearable clearable
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
@ -43,16 +43,16 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="收款状态" prop="collectionStatus"> <!-- <el-form-item label="收款状态" prop="collectionStatus">-->
<el-select v-model="queryParams.collectionStatus" placeholder="请选择收款状态" clearable> <!-- <el-select v-model="queryParams.collectionStatus" placeholder="请选择收款状态" clearable>-->
<el-option <!-- <el-option-->
v-for="dict in dict.type.collection_status" <!-- v-for="dict in dict.type.collection_status"-->
:key="dict.value" <!-- :key="dict.value"-->
:label="dict.label" <!-- :label="dict.label"-->
:value="dict.value" <!-- :value="dict.value"-->
/> <!-- />-->
</el-select> <!-- </el-select>-->
</el-form-item> <!-- </el-form-item>-->
<!-- <el-form-item label="开票状态" prop="invoiceStatus"> <!-- <el-form-item label="开票状态" prop="invoiceStatus">
<el-select v-model="queryParams.invoiceStatus" placeholder="请选择开票状态" clearable> <el-select v-model="queryParams.invoiceStatus" placeholder="请选择开票状态" clearable>
<el-option <el-option
@ -66,9 +66,9 @@
<el-form-item label="预计收款时间"> <el-form-item label="预计收款时间">
<el-date-picker <el-date-picker
v-model="estimatedReceiptDateRange" v-model="estimatedReceiptDateRange"
style="width: 240px" style="width: 300px"
value-format="yyyy-MM-dd HH:mm:ss" value-format="yyyy-MM-dd HH:mm:ss"
type="daterange" type="datetimerange"
range-separator="-" range-separator="-"
start-placeholder="开始日期" start-placeholder="开始日期"
end-placeholder="结束日期" end-placeholder="结束日期"
@ -82,13 +82,13 @@
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5" > <el-col :span="1.5" >
<el-button type="primary" plain icon="el-icon-plus" @click="handleMergeAndInitiateReceipt" v-hasPermi="['finance:receivable:mergeReceipt']"> <el-button type="primary" plain @click="handleMergeAndInitiateReceipt" v-hasPermi="['finance:receipt:generate']">
合并发起收款单 合并发起收款单
</el-button> </el-button>
</el-col> </el-col>
<el-col :span="1.5" > <el-col :span="1.5" >
<el-button type="primary" plain icon="el-icon-plus" @click="handleMergeAndInitiateInvoice" v-hasPermi="['finance:receivable:mergeInvoice']"> <el-button type="primary" plain @click="handleMergeAndInitiateInvoice" v-hasPermi="['finance:invoice:generate']">
合并发起开票单 合并发起开票单
</el-button> </el-button>
</el-col> </el-col>
@ -97,22 +97,26 @@
<el-table v-loading="loading" :data="receivableList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="receivableList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" /> <el-table-column type="selection" width="50" />
<el-table-column label="项目编号" align="center" prop="projectCode" width="120" /> <!-- <el-table-column label="项目编号" align="center" prop="projectCode" width="120" />-->
<el-table-column label="项目名称" align="center" prop="projectName" width="150" /> <el-table-column label="项目名称" align="center" prop="projectName" width="240" />
<el-table-column label="应收单编号" align="center" prop="receivableBillCode" width="150" /> <el-table-column label="销售-应收单编号" align="center" prop="receivableBillCode" width="150" />
<el-table-column label="预计收款时间" align="center" prop="planReceiptDate" width="180"/> <el-table-column label="预计收款时间" align="center" prop="planReceiptDate" width="180"/>
<el-table-column label="预计收款金额" align="center" prop="planAmount" width="120" /> <el-table-column label="预计收款金额" align="center" prop="planAmount" width="120" />
<!-- <el-table-column label="该客户是否有预收单" align="center" prop="hasAdvanceReceipt" width="150" /> --> <el-table-column label="该进货商是否有预收单" align="center" prop="hasAdvanceReceipt" width="150" >
<template slot-scope="scope">
{{ scope.row.remainingAmount == 0 ? '否' : '是' }}
</template>
</el-table-column>
<el-table-column label="进货商名称" align="center" prop="partnerName" width="150" /> <el-table-column label="进货商名称" align="center" prop="partnerName" width="150" />
<el-table-column label="产品类型" align="center" prop="productType" width="120"> <el-table-column label="产品类型" align="center" prop="productType" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.product_type" :value="scope.row.productType"/> <dict-tag :options="dict.type.product_type" :value="scope.row.productType"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="含税总价" align="center" prop="totalPriceWithTax" width="120" /> <el-table-column label="含税总价(元)" align="center" prop="totalPriceWithTax" width="120" />
<el-table-column label="未收款金额" align="center" prop="unreceivedAmount" width="120" /> <el-table-column label="未收款金额" align="center" prop="unreceivedAmount" width="120" />
<el-table-column label="未开票金额" align="center" prop="uninvoicedAmount" width="120" /> <el-table-column label="未开票金额" align="center" prop="uninvoicedAmount" width="120" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160" fixed="right"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="300" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
size="mini" size="mini"
@ -127,15 +131,16 @@
icon="el-icon-edit" icon="el-icon-edit"
v-show="scope.row.unreceivedAmount!==0" v-show="scope.row.unreceivedAmount!==0"
@click="handleGeneratedReceipt(scope.row)" @click="handleGeneratedReceipt(scope.row)"
v-hasPermi="['finance:receivable:edit']" v-hasPermi="['finance:receipt:generate']"
>生成收款单</el-button> >生成收款单</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-delete" icon="el-icon-edit"
@click="handleDelete(scope.row)" v-show="scope.row.unreceivedAmount!==0"
v-hasPermi="['finance:receivable:remove']" @click="handleGeneratedInvoice(scope.row)"
>删除</el-button> v-hasPermi="['finance:invoice:generate']"
>生成收票单</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -194,7 +199,7 @@ export default {
projectCode: null, projectCode: null,
projectName: null, projectName: null,
receivableBillCode: null, receivableBillCode: null,
customerName: null, partnerName: null,
productType: null, productType: null,
collectionStatus: null, collectionStatus: null,
createTimeStart: null, createTimeStart: null,
@ -217,15 +222,10 @@ export default {
/** 查询销售应收单列表 */ /** 查询销售应收单列表 */
getList() { getList() {
this.loading = true; this.loading = true;
if (null != this.dateRange && '' != this.dateRange) { let query = { ...this.queryParams };
this.queryParams.createTimeStart = this.dateRange[0]; query = this.addDateRange(query, this.estimatedReceiptDateRange, 'PlanReceiptDate');
this.queryParams.createTimeEnd = this.dateRange[1];
} listReceivable(query).then(response => {
if (null != this.estimatedReceiptDateRange && '' != this.estimatedReceiptDateRange) {
this.queryParams.estimatedReceiptTimeStart = this.estimatedReceiptDateRange[0];
this.queryParams.estimatedReceiptTimeEnd = this.estimatedReceiptDateRange[1];
}
listReceivable(this.queryParams).then(response => {
this.receivableList = response.rows; this.receivableList = response.rows;
this.total = response.total; this.total = response.total;
this.loading = false; this.loading = false;
@ -268,6 +268,10 @@ export default {
this.selectedReceivableRows=[row] this.selectedReceivableRows=[row]
this.handleMergeAndInitiateReceipt() this.handleMergeAndInitiateReceipt()
}, },
handleGeneratedInvoice(row) {
this.selectedReceivableRows=[row]
this.handleMergeAndInitiateInvoice()
},
/** 合并并发起收款单按钮操作 */ /** 合并并发起收款单按钮操作 */
handleMergeAndInitiateReceipt() { handleMergeAndInitiateReceipt() {
if (this.selectedReceivableRows.length === 0) { if (this.selectedReceivableRows.length === 0) {
@ -275,7 +279,7 @@ export default {
return; return;
} }
let customerLength = new Set(this.selectedReceivableRows.map(item=>item.customerCode)).size; // Use customerCode to differentiate let customerLength = new Set(this.selectedReceivableRows.map(item=>item.customerCode)).size; // Use customerCode to differentiate
// Or check customerName if code is not available in row, but row usually has it. // Or check partnerName if code is not available in row, but row usually has it.
if (customerLength > 1) { if (customerLength > 1) {
this.$modal.msgWarning("请选择同一家客户的应收单进行合并操作"); this.$modal.msgWarning("请选择同一家客户的应收单进行合并操作");
return; return;

View File

@ -4,8 +4,9 @@
<el-form ref="form" :model="form" :rules="rules" label-width="120px"> <el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="代理商" prop="partnerName"> <el-form-item label="进货商名称" prop="partnerName">
<el-input v-model="form.partnerName" placeholder="请选择代理商" readonly @click.native="showPartnerSelector = true"> <el-input v-model="form.partnerName" placeholder="请选择进货商" readonly
@click.native="showPartnerSelector = true">
<el-button slot="append" icon="el-icon-search" @click="showPartnerSelector = true"></el-button> <el-button slot="append" icon="el-icon-search" @click="showPartnerSelector = true"></el-button>
</el-input> </el-input>
</el-form-item> </el-form-item>
@ -13,27 +14,25 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="是否预收" prop="receiveBillType"> <el-form-item label="备注" prop="receiveBillType">
<el-radio-group v-model="form.receiveBillType"> <el-checkbox v-model="form.receiveBillType" true-label="PRE_RECEIPT" false-label="FROM_RECEIVABLE">
<el-radio label="PRE_RECEIPT"></el-radio> </el-checkbox>
<el-radio label="FROM_RECEIVABLE"></el-radio>
</el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <!-- <el-row>-->
<el-col :span="24"> <!-- <el-col :span="24">-->
<el-form-item label="预计收款时间" prop="receiptTime"> <!-- <el-form-item label="预计收款时间" prop="receiptTime">-->
<el-date-picker <!-- <el-date-picker-->
v-model="form.receiptTime" <!-- v-model="form.receiptTime"-->
type="date" <!-- type="date"-->
value-format="yyyy-MM-dd HH:mm:ss" <!-- value-format="yyyy-MM-dd HH:mm:ss"-->
placeholder="选择日期" <!-- placeholder="选择日期"-->
></el-date-picker> <!-- ></el-date-picker>-->
</el-form-item> <!-- </el-form-item>-->
</el-col> <!-- </el-col>-->
</el-row> <!-- </el-row>-->
<el-row v-if="form.receiveBillType === 'PRE_RECEIPT'"> <el-row v-if="form.receiveBillType === 'PRE_RECEIPT'">
<el-col :span="12"> <el-col :span="12">
@ -52,37 +51,43 @@
ref="receivableTable" ref="receivableTable"
:data="receivableList" :data="receivableList"
border border
v-loading="receivableLoading"
style="width: 100%" style="width: 100%"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
max-height="400" max-height="400"
row-key="id" row-key="id"
> >
<el-table-column type="selection" width="55" reserve-selection></el-table-column> <el-table-column type="selection" width="55" reserve-selection></el-table-column>
<el-table-column label="应收单编号" align="center" prop="receivableBillCode" width="150"/> <el-table-column label="销售-应收单编号" align="center" prop="receivableBillCode" width="150"/>
<el-table-column label="预计收款时间" align="center" prop="planReceiptDate" width="180"/> <el-table-column label="预计收款时间" align="center" prop="planReceiptDate" width="180"/>
<el-table-column label="收款计划" align="center" width="100" prop="planAmount"> <!-- <el-table-column label="收款计划" align="center" width="100" prop="planAmount">-->
<!-- </el-table-column>-->
<el-table-column label="预期收款金额">
<template slot-scope="scope">
{{ calculateOrderCurrentReceiptAmount(scope.row).toFixed(2) }}
</template>
</el-table-column> </el-table-column>
<!-- <el-table-column label="项目名称" align="center" prop="projectName" width="150"/> --> <el-table-column label="预期收款比例" align="center" width="120">
<el-table-column label="合同编号" align="center" prop="orderCode" width="150"/> <template slot-scope="scope">
<el-table-column label="出入库单号" align="center" prop="inventoryCode" width="150"/> {{ calculateOrderCurrentReceiptRate(scope.row) }}
</template>
</el-table-column>
<el-table-column label="项目名称" align="center" prop="projectName" width="150"/>
<el-table-column label="进货商名称" align="center" prop="partnerName" width="150"/>
<!-- <el-table-column label="出入库单号" align="center" prop="inventoryCode" width="150"/>-->
<!-- <el-table-column label="收款状态" align="center" prop="collectionStatus" width="120"> <!-- <el-table-column label="收款状态" align="center" prop="collectionStatus" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.collection_status" :value="scope.row.collectionStatus"/> <dict-tag :options="dict.type.collection_status" :value="scope.row.collectionStatus"/>
</template> </template>
</el-table-column> --> </el-table-column> -->
<el-table-column label="含税总价" align="center" prop="totalPriceWithTax" width="120"/> <el-table-column label="含税总价(元)" align="center" prop="totalPriceWithTax" width="120"/>
<el-table-column label="未收款金额" align="center" prop="unreceivedAmount" width="120"/> <el-table-column label="未收款金额(元)" align="center" prop="unreceivedAmount" width="120"/>
<el-table-column label="本次收款金额"> <el-table-column label="已收款金额(元)" align="center" prop="receivedAmount" width="120"/>
<el-table-column label="收款中金额(元)" align="center" prop="receivedAmount" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
{{ calculateOrderCurrentReceiptAmount(scope.row).toFixed(2) }} {{ $calc.sub($calc.sub(scope.row.totalPriceWithTax, scope.row.receivedAmount), scope.row.unreceivedAmount) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="本次收款比例" align="center" width="120">
<template slot-scope="scope">
{{ calculateOrderCurrentReceiptRate(scope.row) }}%
</template>
</el-table-column>
<el-table-column label="已收款金额" align="center" prop="receivedAmount" width="120"/>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100" <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100"
fixed="right"> fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
@ -118,6 +123,7 @@
ref="orderTable" ref="orderTable"
:data="orderList" :data="orderList"
border border
v-loading="orderLoading"
style="width: 100%" style="width: 100%"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
@select="handleSelect" @select="handleSelect"
@ -145,7 +151,7 @@
</div> </div>
<div v-if="!form.partnerCode" style="text-align: center; color: #909399; padding: 20px;"> <div v-if="!form.partnerCode" style="text-align: center; color: #909399; padding: 20px;">
请先选择代理 请先选择进货
</div> </div>
</div> </div>
@ -210,6 +216,8 @@ export default {
actualReceiveTime: null actualReceiveTime: null
}, },
showPartnerSelector: false, showPartnerSelector: false,
receivableLoading: false,
orderLoading: false,
rules: { rules: {
partnerName: [{required: true, message: "代理商不能为空", trigger: "change"}], partnerName: [{required: true, message: "代理商不能为空", trigger: "change"}],
actualReceiveTime: [{required: true, message: "实际收款时间不能为空", trigger: "change"}], actualReceiveTime: [{required: true, message: "实际收款时间不能为空", trigger: "change"}],
@ -284,6 +292,7 @@ export default {
if (this.form.receiveBillType === 'FROM_RECEIVABLE' && this.form.partnerCode) { if (this.form.receiveBillType === 'FROM_RECEIVABLE' && this.form.partnerCode) {
query.partnerCode = this.form.partnerCode; query.partnerCode = this.form.partnerCode;
this.receivableLoading = true
listReceivable(query).then(res => { listReceivable(query).then(res => {
this.receivableList = (res.rows || []).map(item => { this.receivableList = (res.rows || []).map(item => {
const receiptPlans = item.receiptPlans ? [...item.receiptPlans] : []; const receiptPlans = item.receiptPlans ? [...item.receiptPlans] : [];
@ -302,14 +311,17 @@ export default {
} }
}); });
this.total = res.total; this.total = res.total;
this.receivableLoading = false
}); });
} else if (this.form.receiveBillType === 'PRE_RECEIPT' && this.form.partnerCode) { } else if (this.form.receiveBillType === 'PRE_RECEIPT' && this.form.partnerCode) {
// Filter Sales Orders for the agent (partner) // Filter Sales Orders for the agent (partner)
query.partnerCode = this.form.partnerCode; query.partnerCode = this.form.partnerCode;
query.orderStatus = '2'; // Example status query.orderStatus = '2'; // Example status
this.orderLoading=true
listOrder(query).then(res => { listOrder(query).then(res => {
this.orderList = res.rows || []; this.orderList = res.rows || [];
this.total = res.total; this.total = res.total;
this.orderLoading=false
}); });
} }
this.$nextTick(() => { this.$nextTick(() => {

View File

@ -4,10 +4,10 @@
<el-row :gutter="20"> <el-row :gutter="20">
<!-- Left Side: Form Data --> <!-- Left Side: Form Data -->
<el-col :span="12"> <el-col :span="12">
<div class="form-tip">请选择客户的方式并确认客户打款的账户信息提交至财务审批</div> <div class="form-tip">请选择客户的付方式并确认客户打款的账户信息提交至财务审批</div>
<el-form ref="form" :model="form" label-width="120px" size="small"> <el-form ref="form" :model="form" label-width="120px" size="small">
<el-form-item label="方式" prop="receiptMethod"> <el-form-item label="付方式" prop="receiptMethod">
<el-select v-model="form.receiptMethod" placeholder="请选择方式" style="width: 100%"> <el-select v-model="form.receiptMethod" placeholder="请选择付方式" style="width: 100%">
<el-option <el-option
v-for="dict in dicts.payment_method" v-for="dict in dicts.payment_method"
:key="dict.value" :key="dict.value"
@ -51,7 +51,7 @@
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="含税金额" prop="totalPriceWithTax"> <el-form-item label="收款金额" prop="totalPriceWithTax">
<el-input v-model="form.totalPriceWithTax" :disabled="true"/> <el-input v-model="form.totalPriceWithTax" :disabled="true"/>
</el-form-item> </el-form-item>
@ -203,6 +203,10 @@ export default {
this.previewUrl = ''; this.previewUrl = '';
}, },
handleSubmit() { handleSubmit() {
if (this.$calc.sub(this.form.totalPriceWithTax,this.form.confirmAmount)!=0){
this.$modal.msgError("确认收款金额与收款金额需相同");
return
}
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
// Construct FormData // Construct FormData
@ -218,6 +222,7 @@ export default {
formData.append("file", this.form.file); formData.append("file", this.form.file);
} }
// Since applyPaymentApi usually takes JSON, we might need to verify if backend supports FormData // Since applyPaymentApi usually takes JSON, we might need to verify if backend supports FormData
// Assuming we are sending FormData now. // Assuming we are sending FormData now.
applyReceipt(formData).then(response => { applyReceipt(formData).then(response => {

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="150px">
<el-form-item label="项目编号" prop="projectCode"> <el-form-item label="项目编号" prop="projectCode">
<el-input <el-input
v-model="queryParams.projectCode" v-model="queryParams.projectCode"
@ -17,23 +17,23 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="收款单编号" prop="receiveBillCode"> <el-form-item label="销售-收款单编号" prop="receiptBillCode">
<el-input <el-input
v-model="queryParams.receiveBillCode" v-model="queryParams.receiptBillCode"
placeholder="请输入收款单编号" placeholder="请输入收款单编号"
clearable clearable
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="客户名称" prop="customerName"> <el-form-item label="进货商名称" prop="partnerName">
<el-input <el-input
v-model="queryParams.customerName" v-model="queryParams.partnerName"
placeholder="请输入客户名称" placeholder="请输入进货商名称"
clearable clearable
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="应收单编号" prop="receivableBillCode"> <el-form-item label="销售-应收单编号" prop="receivableBillCode">
<el-input <el-input
v-model="queryParams.receivableBillCode" v-model="queryParams.receivableBillCode"
placeholder="请输入应收单编号" placeholder="请输入应收单编号"
@ -41,23 +41,25 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="收款单类型" prop="receiveBillType"> <el-form-item label="备注" prop="receiveBillType">
<el-select v-model="queryParams.receiveBillType" placeholder="请选择收款单类型" clearable> <el-select v-model="queryParams.receiveBillType" placeholder="请选择" clearable>
<el-option v-for="dict in dict.type.receive_bill_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option> <el-option v-for="dict in dict.type.receive_bill_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="支付方式" prop="receiptMethod">
<el-select v-model="queryParams.receiptMethod" placeholder="请选择" clearable>
<el-option v-for="dict in dict.type.payment_method" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="审批状态" prop="approveStatus"> <el-form-item label="审批状态" prop="approveStatus">
<el-select v-model="queryParams.approveStatus" placeholder="请选择审批状态" clearable> <el-select v-model="queryParams.approveStatus" placeholder="请选择审批状态" clearable>
<el-option label="待提交" value="0" /> <el-option v-for="dict in dict.type.approve_status" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-option label="审批中" value="1" />
<el-option label="已审批" value="2" />
<el-option label="已驳回" value="3" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="收款状态" prop="receiveStatus"> <el-form-item label="收款状态" prop="receiveStatus">
<el-select v-model="queryParams.receiveStatus" placeholder="请选择收款状态" clearable> <el-select v-model="queryParams.receiptStatus" placeholder="请选择收款状态" clearable>
<el-option label="待收款" value="0" /> <el-option v-for="dict in dict.type.receipt_bill_status" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-option label="已收款" value="1" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="审批节点" prop="approveNode"> <el-form-item label="审批节点" prop="approveNode">
@ -72,8 +74,8 @@
<el-date-picker <el-date-picker
v-model="dateRangeApproval" v-model="dateRangeApproval"
style="width: 240px" style="width: 240px"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd HH:mm:ss"
type="daterange" type="datetimerange"
range-separator="-" range-separator="-"
start-placeholder="开始日期" start-placeholder="开始日期"
end-placeholder="结束日期" end-placeholder="结束日期"
@ -83,8 +85,8 @@
<el-date-picker <el-date-picker
v-model="dateRangeEstimated" v-model="dateRangeEstimated"
style="width: 240px" style="width: 240px"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd HH:mm:ss"
type="daterange" type="datetimerange"
range-separator="-" range-separator="-"
start-placeholder="开始日期" start-placeholder="开始日期"
end-placeholder="结束日期" end-placeholder="结束日期"
@ -94,8 +96,8 @@
<el-date-picker <el-date-picker
v-model="dateRangeActual" v-model="dateRangeActual"
style="width: 240px" style="width: 240px"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd HH:mm:ss"
type="daterange" type="datetimerange"
range-separator="-" range-separator="-"
start-placeholder="开始日期" start-placeholder="开始日期"
end-placeholder="结束日期" end-placeholder="结束日期"
@ -121,26 +123,26 @@
</el-row> </el-row>
<el-table v-loading="loading" :data="receiveList"> <el-table v-loading="loading" :data="receiveList">
<el-table-column label="收款单编号" align="center" prop="receiptBillCode" /> <el-table-column label="销售-收款单编号" align="center" prop="receiptBillCode" width="180" />
<el-table-column label="预计收款时间" align="center" prop="receiptTime" width="180"> <el-table-column label="预计收款时间" align="center" prop="receiptTime" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.receiptTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span> <span>{{ parseTime(scope.row.receiptTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="进货商名称" align="center" prop="partnerName" /> <el-table-column label="进货商名称" align="center" prop="partnerName" width="230" />
<el-table-column label="含税总价(元)" align="center" prop="totalPriceWithTax" /> <el-table-column label="含税总价(元)" align="center" prop="totalPriceWithTax" width="180" />
<el-table-column label="收款单类型" align="center" prop="receiptBillType" > <el-table-column label="备注" align="center" prop="receiptBillType" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.receipt_bill_type" :value="scope.row.receiptBillType"/> <dict-tag :options="dict.type.receipt_bill_type" :value="scope.row.receiptBillType"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="预收单剩余额度" align="center" prop="remainingAmount" /> <el-table-column label="预收单剩余额度" align="center" prop="remainingAmount" width="180"/>
<el-table-column label="收款状态" align="center" prop="receiveStatus" > <el-table-column label="收款状态" align="center" prop="receiveStatus" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.receipt_bill_status" :value="scope.row.receiptStatus"/> <dict-tag :options="dict.type.receipt_bill_status" :value="scope.row.receiptStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="审批状态" align="center" prop="approveStatus" > <el-table-column label="审批状态" align="center" prop="approveStatus" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.approve_status" :value="scope.row.approveStatus"/> <dict-tag :options="dict.type.approve_status" :value="scope.row.approveStatus"/>
</template> </template>
@ -150,8 +152,8 @@
<span>{{ parseTime(scope.row.approveTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span> <span>{{ parseTime(scope.row.approveTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="审批节点" align="center" prop="approveNode" /> <el-table-column label="审批节点" align="center" prop="approveNode" width="200" fixed="right" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="300" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
size="mini" size="mini"
@ -163,27 +165,38 @@
size="mini" size="mini"
type="text" type="text"
icon="el-icon-document" icon="el-icon-document"
v-show="(scope.row.receiptBillType==='FROM_RECEIVABLE' && scope.row.approveStatus!=='0') ||
(scope.row.receiptBillType!=='FROM_RECEIVABLE' && scope.row.approveStatus==='2') "
@click="handleReceipt(scope.row)" @click="handleReceipt(scope.row)"
>附件</el-button> >{{scope.row.receiptBillType!=='REFUND'?'客户付款图':'退款回执单'}}</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-money" icon="el-icon-money"
v-show="scope.row.receiptBillType==='FROM_RECEIVABLE' && scope.row.receiptStatus==='1' && scope.row.approveStatus==='0'"
@click="handleApplyPayment(scope.row)" @click="handleApplyPayment(scope.row)"
>申请</el-button> >申请</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-money" icon="el-icon-money"
v-show="scope.row.receiptBillType==='FROM_RECEIVABLE' && scope.row.receiptStatus==='2' && scope.row.approveStatus==='2'"
@click="handleApplyRefund(scope.row)" @click="handleApplyRefund(scope.row)"
>申请退款</el-button> >申请退款</el-button>
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-document" icon="el-icon-document"
v-show="scope.row.receiptBillType==='FROM_RECEIVABLE' && scope.row.receiptStatus==='1' &&(scope.row.approveStatus==='0' || scope.row.approveStatus==='3') " v-show="scope.row.receiptBillType==='FROM_RECEIVABLE' && scope.row.receiptStatus==='1' && scope.row.approveStatus==='0' "
@click="handleReturn(scope.row)" @click="handleReturn(scope.row)"
>退回</el-button> >退回</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-refresh-right"
v-if="(scope.row.approveStatus === '2' || scope.row.approveStatus==='3') && (scope.row.receiptStatus==='1'||scope.row.receiptStatus==='3')"
@click="handleRevoke(scope.row)"
>撤销</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -211,7 +224,7 @@
</template> </template>
<script> <script>
import {listReceive, getReceive, redRush, mergeReceivable, returnReceive, addReceipt} from "@/api/finance/receive"; import {listReceive, getReceive, redRush, mergeReceivable, returnReceive, addReceipt, revokeReceipt} from "@/api/finance/receive";
import { addDateRange } from "@/utils/ruoyi"; import { addDateRange } from "@/utils/ruoyi";
import DetailDrawer from "./components/DetailDrawer.vue"; import DetailDrawer from "./components/DetailDrawer.vue";
import AddForm from "./components/AddForm.vue"; import AddForm from "./components/AddForm.vue";
@ -245,8 +258,8 @@ export default {
pageSize: 10, pageSize: 10,
projectCode: null, projectCode: null,
projectName: null, projectName: null,
receiveBillCode: null, receiptBillCode: null,
customerName: null, partnerName: null,
receivableBillCode: null, receivableBillCode: null,
receiveBillType: null, receiveBillType: null,
approveStatus: null, approveStatus: null,
@ -308,7 +321,7 @@ export default {
}, },
/** 新增提交 */ /** 新增提交 */
handleAddSubmit(form) { handleAddSubmit(form) {
if (form.paymentBillType==='FROM_RECEIVABLE'){ if (form.receiptBillType==='FROM_RECEIVABLE'){
mergeReceivable(form).then(response => { mergeReceivable(form).then(response => {
this.$modal.msgSuccess("新增成功"); this.$modal.msgSuccess("新增成功");
this.addOpen = false; this.addOpen = false;
@ -351,9 +364,19 @@ export default {
this.currentRow = row; this.currentRow = row;
this.receiptOpen = true; this.receiptOpen = true;
}, },
/** 撤销按钮操作 */
handleRevoke(row) {
let msg = row.receiptBillType === 'REFUND' ? '是否将该笔销售-退款单撤销,将退款单撤销至收款单' : '是否将该笔销售-收款单撤销,撤销至收款单未审批状态';
this.$modal.confirm(msg).then(() => {
return revokeReceipt(row.id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("撤销成功");
}).catch(() => {});
},
/** 退回按钮操作 */ /** 退回按钮操作 */
handleRedRush(row) { handleRedRush(row) {
this.$modal.confirm('是否确认收款单编号为"' + row.receiveBillCode + '"的数据项进行红冲,并提交财务审批?').then(function() { this.$modal.confirm('是否确认收款单编号为"' + row.receiptBillCode + '"的数据项进行红冲,并提交财务审批?').then(function() {
return redRush(row.id); return redRush(row.id);
}).then(() => { }).then(() => {
this.getList(); this.getList();

View File

@ -149,9 +149,21 @@ process:
financeRefund: finance_refund financeRefund: finance_refund
fiananceTicket: fianance_ticket fiananceTicket: fianance_ticket
financeTicketRefound: finance_ticket_refound financeTicketRefound: finance_ticket_refound
financeReceiptApprove: finance_receipt_approve
financeReceiptRefound: finance_receipt_refound
financeInvoiceApprove: finance_invoice_approve
financeInvoiceRefound: finance_invoice_refound
#业务执行实例bean name ,可以按审批节点配置 业务审批回调方法处理业务逻辑. key 为流程节点主键ID value 要执行的业务方法名称,不配置则默认调用TodoCommonTemplate.todoApproveCallback #业务执行实例bean name ,可以按审批节点配置 业务审批回调方法处理业务逻辑. key 为流程节点主键ID value 要执行的业务方法名称,不配置则默认调用TodoCommonTemplate.todoApproveCallback
instance: instance:
financeReceiptApprove:
beanName: omsReceiptBillServiceImpl
financeReceiptRefound:
beanName: omsReceiptBillServiceImpl
financeInvoiceApprove:
beanName: omsInvoiceBillServiceImpl
financeInvoiceRefound:
beanName: omsInvoiceBillServiceImpl
orderApproveOnline: orderApproveOnline:
beanName: projectOrderInfoServiceImpl beanName: projectOrderInfoServiceImpl
orderApproveOffline: orderApproveOffline:

View File

@ -17,5 +17,9 @@ public class Definition {
private String financeRefund; private String financeRefund;
private String fiananceTicket; private String fiananceTicket;
private String financeTicketRefound; private String financeTicketRefound;
private String financeReceiptApprove;
private String financeReceiptRefound;
private String financeInvoiceApprove;
private String financeInvoiceRefound;
} }

View File

@ -19,6 +19,10 @@ public class Instance {
private Map<String, Object> finance_refund; private Map<String, Object> finance_refund;
private Map<String, Object> fianance_ticket; private Map<String, Object> fianance_ticket;
private Map<String, Object> finance_ticket_refound; private Map<String, Object> finance_ticket_refound;
private Map<String, Object> finance_receipt_approve;
private Map<String, Object> finance_receipt_refound;
private Map<String, Object> finance_invoice_approve;
private Map<String, Object> finance_invoice_refound;
} }

View File

@ -1,6 +1,7 @@
package com.ruoyi.sip.controller; package com.ruoyi.sip.controller;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.config.flow.ProcessConfig;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
@ -8,6 +9,7 @@ import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.sip.domain.OmsFinAttachment; import com.ruoyi.sip.domain.OmsFinAttachment;
import com.ruoyi.sip.domain.OmsPaymentBill; import com.ruoyi.sip.domain.OmsPaymentBill;
import com.ruoyi.sip.domain.OmsReceiptBill; import com.ruoyi.sip.domain.OmsReceiptBill;
import com.ruoyi.sip.flowable.service.TodoService;
import com.ruoyi.sip.service.IOmsFinAttachmentService; import com.ruoyi.sip.service.IOmsFinAttachmentService;
import com.ruoyi.sip.service.IOmsReceiptBillService; import com.ruoyi.sip.service.IOmsReceiptBillService;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
@ -17,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -35,11 +38,18 @@ public class OmsReceiptBillController extends BaseController {
@Autowired @Autowired
private IOmsFinAttachmentService omsFinAttachmentService; private IOmsFinAttachmentService omsFinAttachmentService;
@Autowired
private TodoService todoService;
@Autowired
private ProcessConfig processConfig;
@GetMapping("/list") @PostMapping("/list")
public TableDataInfo list(OmsReceiptBill omsReceiptBill) { public TableDataInfo list(OmsReceiptBill omsReceiptBill) {
startPage(); startPage();
List<OmsReceiptBill> list = omsReceiptBillService.queryAll(omsReceiptBill); List<OmsReceiptBill> list = omsReceiptBillService.queryAll(omsReceiptBill);
todoService.fillApproveNode(list,
Arrays.asList(processConfig.getDefinition().getFinanceReceiptApprove(), processConfig.getDefinition().getFinanceReceiptRefound())
, OmsReceiptBill::getReceiptBillCode, (a, b) -> a.setApproveNode(b.get(a.getReceiptBillCode())));
return getDataTable(list); return getDataTable(list);
} }
@PostMapping("/write-off/list") @PostMapping("/write-off/list")
@ -51,9 +61,40 @@ public class OmsReceiptBillController extends BaseController {
return getDataTable(list); return getDataTable(list);
} }
@RequiresPermissions("finance:payment:approve")
@PostMapping("/approve/list")
@ResponseBody
public TableDataInfo listApprove(OmsReceiptBill omsReceiptBill) {
startPage();
List<OmsReceiptBill> list = omsReceiptBillService.listApprove(omsReceiptBill);
clearPage();
todoService.fillApproveNode(list,
Collections.singletonList(omsReceiptBill.getProcessKey())
, OmsReceiptBill::getReceiptBillCode, (a, b) -> a.setApproveNode(b.get(a.getReceiptBillCode())));
return getDataTable(list);
}
@RequiresPermissions("finance:payment:approve")
@PostMapping("/approved/list")
@ResponseBody
public TableDataInfo listApproved(OmsReceiptBill omsReceiptBill) {
startPage();
List<OmsReceiptBill> list = omsReceiptBillService.listApproved(omsReceiptBill);
clearPage();
todoService.fillApproveNode(list,
Collections.singletonList(omsReceiptBill.getProcessKey())
, OmsReceiptBill::getReceiptBillCode, (a, b) -> a.setApproveNode(b.get(a.getReceiptBillCode())));
return getDataTable(list);
}
@GetMapping(value = "/{id}") @GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) { public AjaxResult getInfo(@PathVariable("id") Long id) {
return AjaxResult.success(omsReceiptBillService.queryById(id)); OmsReceiptBill data = omsReceiptBillService.queryById(id);
todoService.fillApproveNode(Collections.singletonList(data),
Arrays.asList(processConfig.getDefinition().getFinanceReceiptApprove(), processConfig.getDefinition().getFinanceReceiptRefound())
, OmsReceiptBill::getReceiptBillCode, (a, b) -> a.setApproveNode(b.get(a.getReceiptBillCode())));
return AjaxResult.success(data);
} }
@ -158,4 +199,14 @@ public class OmsReceiptBillController extends BaseController {
return AjaxResult.error("操作失败:" + e.getMessage()); return AjaxResult.error("操作失败:" + e.getMessage());
} }
} }
@PostMapping("/revoke")
@ResponseBody
public AjaxResult revoke(@RequestBody OmsReceiptBill omsReceiptBill) {
try {
return omsReceiptBillService.revoke(omsReceiptBill);
} catch (Exception e) {
logger.error("撤销失败", e);
return AjaxResult.error("操作失败:" + e.getMessage());
}
}
} }

View File

@ -159,6 +159,7 @@ public class OmsInvoiceBill extends BaseEntity
WAIT_INVOICE("1", "未开票"), WAIT_INVOICE("1", "未开票"),
/** 已开票 */ /** 已开票 */
INVOICE("2", "已开票"), INVOICE("2", "已开票"),
WAIT_RED_RUSH("3", "未红冲"),
; ;
private final String code; private final String code;

View File

@ -5,6 +5,7 @@ import java.util.Date;
import java.util.List; import java.util.List;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.sip.domain.dto.ReceiptDetailDTO; import com.ruoyi.sip.domain.dto.ReceiptDetailDTO;
import lombok.Data; import lombok.Data;
import lombok.Getter; import lombok.Getter;
@ -18,7 +19,7 @@ import lombok.Getter;
*/ */
@Data @Data
public class OmsReceiptBill { public class OmsReceiptBill extends BaseEntity {
/** /**
* ID * ID
*/ */
@ -28,6 +29,7 @@ public class OmsReceiptBill {
* *
*/ */
private String receivableBillCode;
private String receiptBillCode; private String receiptBillCode;
private List<String> receiptBillCodeList; private List<String> receiptBillCodeList;
/** /**
@ -165,7 +167,12 @@ public class OmsReceiptBill {
private OmsFinAttachment attachment; private OmsFinAttachment attachment;
private List<ReceiptDetailDTO> detailDTOList; private List<ReceiptDetailDTO> detailDTOList;
private Long approveUser;
private Date applyTime;
private Date todoApproveTime;
private String processKey;
private String todoId;
private String taskId;
private BigDecimal writeOffAmount; private BigDecimal writeOffAmount;
private BigDecimal writeOffAmountWithoutTax; private BigDecimal writeOffAmountWithoutTax;
@ -217,6 +224,7 @@ public class OmsReceiptBill {
WAIT_PAYMENT("1", "未付款"), WAIT_PAYMENT("1", "未付款"),
/** 预付单 */ /** 预付单 */
PAYMENT("2", "已付款"), PAYMENT("2", "已付款"),
WAIT_REFUNDED("3", "未退款"),

View File

@ -73,9 +73,9 @@ public class OmsReceivableInvoiceDetail extends BaseEntity
public enum ReceivableDetailTypeEnum { public enum ReceivableDetailTypeEnum {
/** 正常开票 */ /** 正常开票 */
NORMAL_INVOICE("1", "正常开票"), NORMAL_INVOICE("1", "申请开票"),
/** 红冲 */ /** 红冲 */
REFUND("3", "红冲"), REFUND("3", "申请红冲"),
; ;
private final String code; private final String code;

View File

@ -75,10 +75,10 @@ public class OmsReceivableReceiptDetail extends BaseEntity
public enum ReceivableDetailTypeEnum { public enum ReceivableDetailTypeEnum {
/** 正常收款 */ /** 正常收款 */
NORMAL_RECEIPT("1", "正常收款"), NORMAL_RECEIPT("1", "申请收款"),
/** 预收核销 */ /** 预收核销 */
PRE_RECEIVE_WRITE_OFF("2", "预收核销"), PRE_RECEIVE_WRITE_OFF("2", "预收核销"),
REFUND("3", "退款"), REFUND("3", "申请退款"),
; ;
private final String code; private final String code;

View File

@ -0,0 +1,24 @@
package com.ruoyi.sip.flowable.domain;
import lombok.Data;
/**
* @author : ch
* @version : 1.0
* @ClassName : FlowRelationDto
* @Description :
* @DATE : Created in 9:25 2025/12/29
* <pre> Copyright: Copyright(c) 2025 </pre>
* <pre> Company : </pre>
* Modification History:
* Date Author Version Discription
* --------------------------------------------------------------------------
* 2025/12/29 ch 1.0 Why & What is modified: <> *
*/
@Data
public class FlowRelationDto {
private String querySql;
private String joinSql;
}

View File

@ -3,6 +3,7 @@ package com.ruoyi.sip.flowable.service;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.sip.domain.OmsPurchaseOrder; import com.ruoyi.sip.domain.OmsPurchaseOrder;
import com.ruoyi.sip.domain.ProjectOrderInfo; import com.ruoyi.sip.domain.ProjectOrderInfo;
import com.ruoyi.sip.flowable.domain.FlowRelationDto;
import com.ruoyi.sip.flowable.domain.Todo; import com.ruoyi.sip.flowable.domain.Todo;
import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.runtime.ProcessInstance;
@ -10,6 +11,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier;
/** /**
* Service * Service
@ -143,6 +145,9 @@ public interface TodoService
AjaxResult statisticsTodo(); AjaxResult statisticsTodo();
FlowRelationDto getFlowRelationSql(String tableName, List<String> processKeyList, Long approveUser
, List<String> notInTaskName, Supplier<String> supplier);
} }

View File

@ -2,6 +2,7 @@ package com.ruoyi.sip.flowable.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.ruoyi.common.config.flow.Instance; import com.ruoyi.common.config.flow.Instance;
import com.ruoyi.common.config.flow.ProcessConfig; import com.ruoyi.common.config.flow.ProcessConfig;
@ -15,6 +16,7 @@ import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.sip.domain.OmsPurchaseOrder; import com.ruoyi.sip.domain.OmsPurchaseOrder;
import com.ruoyi.sip.domain.ProjectOrderInfo; import com.ruoyi.sip.domain.ProjectOrderInfo;
import com.ruoyi.sip.flowable.domain.FlowRelationDto;
import com.ruoyi.sip.flowable.domain.Todo; import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.flowable.mapper.TodoMapper; import com.ruoyi.sip.flowable.mapper.TodoMapper;
import com.ruoyi.sip.flowable.service.DeleteFlowableProcessInstanceCmd; import com.ruoyi.sip.flowable.service.DeleteFlowableProcessInstanceCmd;
@ -39,6 +41,7 @@ import java.util.*;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -441,6 +444,42 @@ public class TodoServiceImpl implements TodoService {
return AjaxResult.success(resultMap); return AjaxResult.success(resultMap);
} }
@Override
public FlowRelationDto getFlowRelationSql(String tableName, List<String> processKeyList, Long approveUser, List<String> notInTaskName, Supplier<String> function) {
FlowRelationDto flowRelationDto = new FlowRelationDto();
StringBuilder joinQuerySql = new StringBuilder();
StringBuilder joinSql = new StringBuilder();
if ("bu_todo".equals(tableName)){
joinQuerySql.append( " ,t3.apply_time,t3.process_key,t3.todo_id,t3.task_id");
joinSql.append(" inner join ( ");
joinSql.append(" select bt.business_key,bt.apply_time,bt.process_key,bt.todo_id,bt.task_id from bu_todo bt where ");
joinSql.append(StrUtil.format(" bt.process_key IN ({})", processKeyList.stream().map(processKey -> "'" + processKey + "'").collect(Collectors.joining(","))));
joinSql.append(" AND bt.approve_user = ").append(approveUser).append(" ");
if (CollUtil.isNotEmpty(notInTaskName)) {
joinSql.append(" AND bt.task_name NOT IN (");
joinSql.append(notInTaskName.stream().map(taskName -> "'" + taskName + "'").collect(Collectors.joining(",")));
joinSql.append(") ");
}
joinSql.append(") t3 on t3.business_key =");
}else{
joinQuerySql.append( " ,t3.apply_time,t3.approve_time as todo_approve_time,t3.process_key ");
joinSql.append(" inner join ( SELECT business_key, max(btc.approve_time) approve_time, max(btc.apply_time) apply_time, max(btc.process_key) process_key FROM bu_todo_completed btc");
joinSql.append(StrUtil.format(" where btc.process_key IN ({})", processKeyList.stream().map(processKey -> "'" + processKey + "'").collect(Collectors.joining(","))));
joinSql.append(" AND btc.approve_user = ").append(approveUser).append(" ");
if (CollUtil.isNotEmpty(notInTaskName)) {
joinSql.append(" AND btc.task_name NOT IN (");
joinSql.append(notInTaskName.stream().map(taskName -> "'" + taskName + "'").collect(Collectors.joining(",")));
joinSql.append(") ");
}
joinSql.append(" GROUP BY business_key) t3 on t3.business_key = ");
}
joinSql.append(function.get());
flowRelationDto.setQuerySql(joinQuerySql.toString());
flowRelationDto.setJoinSql(joinSql.toString());
return flowRelationDto;
}
/** /**
* *
*/ */

View File

@ -1,6 +1,8 @@
package com.ruoyi.sip.mapper; package com.ruoyi.sip.mapper;
import com.ruoyi.sip.domain.OmsReceiptBill; import com.ruoyi.sip.domain.OmsReceiptBill;
import com.ruoyi.sip.flowable.domain.FlowRelationDto;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@ -55,4 +57,9 @@ public interface OmsReceiptBillMapper {
OmsReceiptBill queryByCode(String code); OmsReceiptBill queryByCode(String code);
void updateReturnWriteOffBatch(List<OmsReceiptBill> updateBills); void updateReturnWriteOffBatch(List<OmsReceiptBill> updateBills);
List<OmsReceiptBill> listApprove(@Param("entity") OmsReceiptBill omsReceiptBill, @Param("flowRelationDto") FlowRelationDto flowRelationDto);
void revoke(OmsReceiptBill omsReceiptBill);
} }

View File

@ -73,4 +73,6 @@ public interface OmsReceivableReceiptDetailMapper
void updateWriteOffIdBatch(List<OmsReceivableReceiptDetail> updateList); void updateWriteOffIdBatch(List<OmsReceivableReceiptDetail> updateList);
void clearWriteOffByWriteOffId(List<Long> ids); void clearWriteOffByWriteOffId(List<Long> ids);
void deleteByBillCode(String receiptBillCode);
} }

View File

@ -62,6 +62,12 @@ public interface IOmsReceiptBillService {
void returnWriteOff(List<String> collect, List<OmsReceivableReceiptDetail> omsReceivableReceiptDetails); void returnWriteOff(List<String> collect, List<OmsReceivableReceiptDetail> omsReceivableReceiptDetails);
List<OmsReceiptBill> listWriteOff(OmsReceiptBill omsReceiptBill); List<OmsReceiptBill> listWriteOff(OmsReceiptBill omsReceiptBill);
List<OmsReceiptBill> listApprove(OmsReceiptBill omsReceiptBill);
List<OmsReceiptBill> listApproved(OmsReceiptBill omsReceiptBill);
AjaxResult revoke(OmsReceiptBill omsReceiptBill);
} }

View File

@ -82,4 +82,7 @@ public interface IOmsReceivableReceiptDetailService
void clearWriteOffByWriteOffId(List<Long> ids); void clearWriteOffByWriteOffId(List<Long> ids);
List<OmsReceivableReceiptDetail> listByPlanIdList(List<Long> planIdList); List<OmsReceivableReceiptDetail> listByPlanIdList(List<Long> planIdList);
void deleteByBillCode(String receiptBillCode);
} }

View File

@ -425,28 +425,21 @@ public class OmsPayableBillServiceImpl implements IOmsPayableBillService {
List<OmsPayablePaymentDetail> omsPayablePaymentDetails = omsPayablePaymentDetailService.listByPayableBillIdList(idList); List<OmsPayablePaymentDetail> omsPayablePaymentDetails = omsPayablePaymentDetailService.listByPayableBillIdList(idList);
// 1. 构建 payableBillId -> (paymentPlanId -> 最新PaymentDetail) 的 Map // 1. 构建 payableBillId -> (paymentPlanId -> 最新PaymentDetail) 的 Map
Map<Long, Map<Long, OmsPayablePaymentDetail>> planMap = Map<Long, List<OmsPayablePaymentDetail>> payableDtailListMap =
omsPayablePaymentDetails.stream() omsPayablePaymentDetails.stream()
.collect(Collectors.groupingBy( .collect(Collectors.groupingBy(OmsPayablePaymentDetail::getPayableBillId ));
OmsPayablePaymentDetail::getPayableBillId,
Collectors.toMap(
OmsPayablePaymentDetail::getPaymentPlanId,
Function.identity(),
(d1, d2) -> d1.getCreateTime().after(d2.getCreateTime()) ? d1 : d2
)
));
for (OmsPayableBill payableBill : omsPayableBills) { for (OmsPayableBill payableBill : omsPayableBills) {
// 2. 获取当前账单的支付明细 Map避免 NPE // 2. 获取当前账单的支付明细 Map避免 NPE
Map<Long, OmsPayablePaymentDetail> paymentDetailMap = List<OmsPayablePaymentDetail> detailList =
planMap.getOrDefault(payableBill.getId(), Collections.emptyMap()); payableDtailListMap.getOrDefault(payableBill.getId(), Collections.emptyList());
if (CollUtil.isNotEmpty(paymentDetailMap)) { if (CollUtil.isNotEmpty(detailList)) {
// 3. 按支付状态汇总金额 // 3. 按支付状态汇总金额
Map<String, BigDecimal> amountMap = Map<String, BigDecimal> amountMap =
paymentDetailMap.values().stream() detailList.stream()
.filter(d -> d.getPaymentAmount() != null) .filter(d -> d.getPaymentAmount() != null)
.collect(Collectors.toMap( .collect(Collectors.toMap(
OmsPayablePaymentDetail::getPaymentStatus, OmsPayablePaymentDetail::getPaymentStatus,
@ -458,7 +451,8 @@ public class OmsPayableBillServiceImpl implements IOmsPayableBillService {
BigDecimal paidAmount = amountMap BigDecimal paidAmount = amountMap
.getOrDefault(OmsPaymentBill.PaymentStatusEnum.PAYMENT.getCode(), BigDecimal.ZERO) .getOrDefault(OmsPaymentBill.PaymentStatusEnum.PAYMENT.getCode(), BigDecimal.ZERO)
.add(amountMap.getOrDefault( .add(amountMap.getOrDefault(
OmsPaymentBill.PaymentStatusEnum.REFUNDED.getCode(), BigDecimal.ZERO)); OmsPaymentBill.PaymentStatusEnum.REFUNDED.getCode(), BigDecimal.ZERO))
.subtract(amountMap.getOrDefault(OmsPaymentBill.PaymentStatusEnum.WAIT_REFUNDED.getCode(), BigDecimal.ZERO));
BigDecimal waitPayAmount = BigDecimal waitPayAmount =
amountMap.getOrDefault( amountMap.getOrDefault(
@ -497,27 +491,20 @@ public class OmsPayableBillServiceImpl implements IOmsPayableBillService {
return 0; return 0;
} }
List<OmsPayableTicketDetail> omsPayableTicketDetails = omsPayableTicketDetailService.listByPayableBillIdList(idList); List<OmsPayableTicketDetail> omsPayableTicketDetails = omsPayableTicketDetailService.listByPayableBillIdList(idList);
Map<Long, Map<Long, OmsPayableTicketDetail>> planMap = Map<Long, List<OmsPayableTicketDetail>> payableListMap =
omsPayableTicketDetails.stream() omsPayableTicketDetails.stream()
.collect(Collectors.groupingBy( .collect(Collectors.groupingBy(OmsPayableTicketDetail::getPayableBillId));
OmsPayableTicketDetail::getPayableBillId,
Collectors.toMap(
OmsPayableTicketDetail::getTicketPlanId,
Function.identity(),
(d1, d2) -> d1.getCreateTime().after(d2.getCreateTime()) ? d1 : d2
)
));
for (OmsPayableBill payableBill : omsPayableBills) { for (OmsPayableBill payableBill : omsPayableBills) {
// 2. 获取当前账单的支付明细 Map避免 NPE // 2. 获取当前账单的支付明细 Map避免 NPE
Map<Long, OmsPayableTicketDetail> paymentDetailMap = List<OmsPayableTicketDetail> detailList =
planMap.getOrDefault(payableBill.getId(), Collections.emptyMap()); payableListMap.getOrDefault(payableBill.getId(), Collections.emptyList());
if (CollUtil.isNotEmpty(paymentDetailMap)) { if (CollUtil.isNotEmpty(detailList)) {
// 3. 按支付状态汇总金额 // 3. 按支付状态汇总金额
Map<String, BigDecimal> amountMap = Map<String, BigDecimal> amountMap =
paymentDetailMap.values().stream() detailList.stream()
.filter(d -> d.getPaymentAmount() != null) .filter(d -> d.getPaymentAmount() != null)
.collect(Collectors.toMap( .collect(Collectors.toMap(
OmsPayableTicketDetail::getTicketStatus, OmsPayableTicketDetail::getTicketStatus,
@ -529,7 +516,8 @@ public class OmsPayableBillServiceImpl implements IOmsPayableBillService {
BigDecimal paidAmount = amountMap BigDecimal paidAmount = amountMap
.getOrDefault(OmsTicketBill.TicketStatusEnum.TICKET.getCode(), BigDecimal.ZERO) .getOrDefault(OmsTicketBill.TicketStatusEnum.TICKET.getCode(), BigDecimal.ZERO)
.add(amountMap.getOrDefault( .add(amountMap.getOrDefault(
OmsTicketBill.TicketStatusEnum.RED_RUSH.getCode(), BigDecimal.ZERO)); OmsTicketBill.TicketStatusEnum.RED_RUSH.getCode(), BigDecimal.ZERO))
.subtract(amountMap.getOrDefault(OmsTicketBill.TicketStatusEnum.WAIT_RED_RUSH.getCode(), BigDecimal.ZERO));
BigDecimal waitPayAmount = BigDecimal waitPayAmount =
amountMap.getOrDefault( amountMap.getOrDefault(

View File

@ -155,7 +155,7 @@ public class OmsPayablePaymentDetailServiceImpl implements IOmsPayablePaymentDet
} }
@Override @Override
public void deleteByPaymentCode(String payableBillCode) { public void deleteByPaymentCode(String paymentBillCode) {
omsPayablePaymentDetailMapper.deleteByPaymentCode(payableBillCode); omsPayablePaymentDetailMapper.deleteByPaymentCode(paymentBillCode);
} }
} }

View File

@ -473,7 +473,7 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
if (OmsPaymentBill.PaymentBillTypeEnum.REFUND.getCode().equals(existBill.getPaymentBillType())){ if (OmsPaymentBill.PaymentBillTypeEnum.REFUND.getCode().equals(existBill.getPaymentBillType())){
// 撤销退款单 // 撤销退款单
deleteOmsPaymentBillById(existBill.getId()); deleteOmsPaymentBillById(existBill.getId());
detailService.deleteByPaymentCode(existBill.getPayableBillCode()); detailService.deleteByPaymentCode(existBill.getPaymentBillCode());
OmsPaymentBill omsPaymentBill = new OmsPaymentBill(); OmsPaymentBill omsPaymentBill = new OmsPaymentBill();
omsPaymentBill.setId(existBill.getOriginalBillId()); omsPaymentBill.setId(existBill.getOriginalBillId());
omsPaymentBill.setRefundStatus(OmsPaymentBill.RefundStatusEnum.WAIT_REFUNDED.getCode()); omsPaymentBill.setRefundStatus(OmsPaymentBill.RefundStatusEnum.WAIT_REFUNDED.getCode());

View File

@ -4,23 +4,31 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.config.flow.ProcessConfig;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.ApproveStatusEnum; import com.ruoyi.common.enums.ApproveStatusEnum;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils; import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.sip.domain.*; import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.domain.dto.ReceiptDetailDTO; import com.ruoyi.sip.domain.dto.ReceiptDetailDTO;
import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.flowable.service.TodoCommonTemplate;
import com.ruoyi.sip.flowable.service.TodoService;
import com.ruoyi.sip.mapper.OmsReceiptBillMapper; import com.ruoyi.sip.mapper.OmsReceiptBillMapper;
import com.ruoyi.sip.service.*; import com.ruoyi.sip.service.*;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.rmi.ServerException;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -31,7 +39,8 @@ import java.util.stream.Collectors;
*/ */
@Service @Service
public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService { @Transactional(rollbackFor = Exception.class)
public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService, TodoCommonTemplate {
@Resource @Resource
private OmsReceiptBillMapper omsReceiptBillMapper; private OmsReceiptBillMapper omsReceiptBillMapper;
@ -45,6 +54,11 @@ public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService {
@Autowired @Autowired
private IOmsReceivableWriteOffService omsReceivableWriteOffService; private IOmsReceivableWriteOffService omsReceivableWriteOffService;
@Autowired
private TodoService todoService;
@Autowired
private ProcessConfig processConfig;
/** /**
* *
* *
@ -82,8 +96,12 @@ public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService {
omsReceiptBill.setCreateTime(DateUtils.getNowDate()); omsReceiptBill.setCreateTime(DateUtils.getNowDate());
omsReceiptBill.setCreateBy(ShiroUtils.getUserId().toString()); omsReceiptBill.setCreateBy(ShiroUtils.getUserId().toString());
omsReceiptBill.setReceiptBillCode(generateReceiptBillCode()); omsReceiptBill.setReceiptBillCode(generateReceiptBillCode());
omsReceiptBill.setReceiptStatus(OmsReceiptBill.ReceiptStatusEnum.WAIT_PAYMENT.getCode()); if (StringUtils.isEmpty(omsReceiptBill.getReceiptStatus())) {
omsReceiptBill.setApproveStatus(ApproveStatusEnum.WAIT_COMMIT.getCode()); omsReceiptBill.setReceiptStatus(OmsReceiptBill.ReceiptStatusEnum.WAIT_PAYMENT.getCode());
}
if (StringUtils.isEmpty(omsReceiptBill.getApproveStatus())) {
omsReceiptBill.setApproveStatus(ApproveStatusEnum.WAIT_COMMIT.getCode());
}
return omsReceiptBillMapper.insert(omsReceiptBill); return omsReceiptBillMapper.insert(omsReceiptBill);
} }
@ -162,6 +180,12 @@ public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService {
@Override @Override
public void applyReceipt(OmsReceiptBill omsReceiptBill, MultipartFile file) throws IOException { public void applyReceipt(OmsReceiptBill omsReceiptBill, MultipartFile file) throws IOException {
OmsReceiptBill receiptBill = queryById(omsReceiptBill.getId());
if (!receiptBill.getApproveStatus().equals(ApproveStatusEnum.WAIT_COMMIT.getCode())){
throw new ServerException("审批状态不为待审批");
}
omsReceiptBill.setApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode()); omsReceiptBill.setApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode());
@ -183,6 +207,15 @@ public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService {
attachment.setFileType(file.getContentType()); attachment.setFileType(file.getContentType());
attachment.setCreateBy(loginUser.getUserId().toString()); attachment.setCreateBy(loginUser.getUserId().toString());
attachmentService.insertOmsFinAttachment(attachment); attachmentService.insertOmsFinAttachment(attachment);
//开始审批
todoService.startProcessDeleteBefore(receiptBill.getReceiptBillCode(), receiptBill.getReceiptBillCode()
, new HashMap<String, Object>() {{
put("applyUserName", ShiroUtils.getSysUser().getUserName());
put("applyUser", ShiroUtils.getUserId());
}}
, processConfig.getDefinition().getFinanceReceiptApprove());
} }
@Override @Override
@ -200,7 +233,12 @@ public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService {
return AjaxResult.error("当前订单已提交审批,请刷新后重试"); return AjaxResult.error("当前订单已提交审批,请刷新后重试");
} }
receiptBill.setApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode()); receiptBill.setApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode());
//todo 开启流程 todoService.startProcessDeleteBefore(receiptBill.getReceiptBillCode(), receiptBill.getReceiptBillCode()
, new HashMap<String, Object>() {{
put("applyUserName", ShiroUtils.getSysUser().getUserName());
put("applyUser", ShiroUtils.getUserId());
}}
, processConfig.getDefinition().getFinanceReceiptRefound());
update(receiptBill); update(receiptBill);
return AjaxResult.success("退款申请成功!"); return AjaxResult.success("退款申请成功!");
} }
@ -230,12 +268,12 @@ public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService {
refundBill.setReceiptBillCode(generateReceiptBillCode()); refundBill.setReceiptBillCode(generateReceiptBillCode());
// 设置新属性 // 设置新属性
refundBill.setReceiptBillType(OmsReceiptBill.ReceiptBillTypeEnum.REFUND.getCode()); refundBill.setReceiptBillType(OmsReceiptBill.ReceiptBillTypeEnum.REFUND.getCode());
refundBill.setReceiptStatus(OmsReceiptBill.ReceiptStatusEnum.WAIT_PAYMENT.getCode()); refundBill.setReceiptStatus(OmsReceiptBill.ReceiptStatusEnum.WAIT_REFUNDED.getCode());
refundBill.setApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode()); refundBill.setApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode());
refundBill.setOriginalBillId(receiptBill.getId()); refundBill.setOriginalBillId(receiptBill.getId());
refundBill.setReceiptTime(null); refundBill.setReceiptTime(DateUtils.getNowDate());
refundBill.setReceiptMethod(omsReceiptBill.getReceiptMethod()); refundBill.setReceiptMethod(omsReceiptBill.getReceiptMethod());
refundBill.setRemark("退款-关联原付款单:" + omsReceiptBill.getReceiptBillCode()); refundBill.setRemark("退款-关联原付款单:" + receiptBill.getReceiptBillCode());
insert(refundBill); insert(refundBill);
@ -245,12 +283,12 @@ public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService {
//4 创建付款明细 //4 创建付款明细
omsReceivableReceiptDetailService.applyRefund(receiptBill.getReceiptBillCode(), refundBill.getReceiptBillCode()); omsReceivableReceiptDetailService.applyRefund(receiptBill.getReceiptBillCode(), refundBill.getReceiptBillCode());
//5. 开始退款审批流程 //5. 开始退款审批流程
// todoService.startProcessDeleteBefore(originalBill.getPaymentBillCode(), originalBill.getPaymentBillCode(), todoService.startProcessDeleteBefore(receiptBill.getReceiptBillCode(), refundBill.getReceiptBillCode(),
// new HashMap<String, Object>() {{ new HashMap<String, Object>() {{
// put("applyUserName", ShiroUtils.getSysUser().getUserName()); put("applyUserName", ShiroUtils.getSysUser().getUserName());
// put("applyUser", ShiroUtils.getUserId()); put("applyUser", ShiroUtils.getUserId());
// }} }}
// , processConfig.getDefinition().getFinanceRefund()); , processConfig.getDefinition().getFinanceReceiptRefound());
return AjaxResult.success("退款申请已提交,新的退款单号为:" + refundBill.getReceiptBillCode()); return AjaxResult.success("退款申请已提交,新的退款单号为:" + refundBill.getReceiptBillCode());
} }
@ -424,6 +462,132 @@ public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService {
return omsReceiptBills; return omsReceiptBills;
} }
@Override
public List<OmsReceiptBill> listApprove(OmsReceiptBill omsReceiptBill) {
omsReceiptBill.setApproveUser(ShiroUtils.getUserId());
return omsReceiptBillMapper.listApprove(omsReceiptBill,
todoService.getFlowRelationSql("bu_todo",
Arrays.asList(omsReceiptBill.getProcessKey()),
ShiroUtils.getUserId(),
Collections.singletonList("商务"),
()->{
return "t1.receipt_bill_code";
}));
}
@Override
public List<OmsReceiptBill> listApproved(OmsReceiptBill omsReceiptBill) {
omsReceiptBill.setApproveUser(ShiroUtils.getUserId());
return omsReceiptBillMapper.listApprove(omsReceiptBill, todoService.getFlowRelationSql("bu_todo_completed",
Arrays.asList(omsReceiptBill.getProcessKey()),
ShiroUtils.getUserId(),
Collections.singletonList("商务"),
()->{
return "t1.receipt_bill_code";
}));
}
@Override
public AjaxResult revoke(OmsReceiptBill omsReceiptBill) {
OmsReceiptBill existBill = queryById(omsReceiptBill.getId());
if (existBill == null){
return AjaxResult.error("收款单不存在,请刷新后重试");
}
if (OmsReceiptBill.ReceiptBillTypeEnum.REFUND.getCode().equals(existBill.getReceiptBillType())){
// 撤销退款单
deleteById(existBill.getId());
omsReceivableReceiptDetailService.deleteByBillCode(existBill.getReceiptBillCode());
OmsReceiptBill updateBill = new OmsReceiptBill();
updateBill.setId(existBill.getOriginalBillId());
updateBill.setRefundStatus(OmsReceiptBill.RefundStatusEnum.WAIT_REFUNDED.getCode());
update(updateBill);
}else{
// 撤销付款单
omsReceiptBill.setApproveStatus(ApproveStatusEnum.WAIT_COMMIT.getCode());
omsReceiptBillMapper.revoke(omsReceiptBill);
}
return AjaxResult.success("撤销成功");
}
@Override
public Object todoDetail(String businessKey, String processKey, String todoId) {
return null;
}
@Override
public Object completedTodoDetail(String businessKey, String processKey, String todoId) {
return null;
}
@Override
public void fillBusinessInfo(List<Todo> todoCompletedList) {
}
@Override
public boolean todoApproveCallback(Todo todo) {
if (CollUtil.isEmpty(todo.getVariables())) {
return TodoCommonTemplate.super.todoApproveCallback(todo);
}
Integer approveBtn = (Integer) todo.getVariables().get("approveBtn");
if (approveBtn == null) {
return TodoCommonTemplate.super.todoApproveCallback(todo);
}
String taskName = todo.getTaskName();
String businessKey = todo.getBusinessKey();
OmsReceiptBill receiptBill = omsReceiptBillMapper.queryByCode(businessKey);
if (approveBtn.equals(0)) {
if (receiptBill != null) {
OmsReceiptBill updateBill = new OmsReceiptBill();
updateBill.setId(receiptBill.getId());
updateBill.setApproveStatus(ApproveStatusEnum.APPROVE_REJECT.getCode());
omsReceiptBillMapper.update(updateBill);
}
}else{
if (todo.getProcessKey().equals(processConfig.getDefinition().getFinanceReceiptApprove()) && taskName.startsWith("财务")){
//处理收款审批
OmsReceiptBill updateBill = new OmsReceiptBill();
updateBill.setId(receiptBill.getId());
updateBill.setApproveStatus(ApproveStatusEnum.APPROVE_COMPLETE.getCode());
updateBill.setActualReceiptTime(DateUtils.getNowDate());
updateBill.setApproveTime(DateUtils.getNowDate());
updateBill.setReceiptStatus(OmsReceiptBill.ReceiptStatusEnum.PAYMENT.getCode());
if (receiptBill.getReceiptBillType().equals(OmsReceiptBill.ReceiptBillTypeEnum.PRE_RECEIPT.getCode())){
updateBill.setRemainingAmount(receiptBill.getTotalPriceWithTax());
}
omsReceiptBillMapper.update(updateBill);
List<OmsReceivableReceiptDetail> omsReceivableReceiptDetailList = omsReceivableReceiptDetailService.listByReceiptBillCode(receiptBill.getReceiptBillCode());
receivableBillService.updateReceiptAmount(omsReceivableReceiptDetailList.stream().map(OmsReceivableReceiptDetail::getReceivableBillId).collect(Collectors.toList()));
}else if(todo.getProcessKey().equals(processConfig.getDefinition().getFinanceReceiptRefound()) && taskName.startsWith("公司领导")){
//处理退款审批
OmsReceiptBill updateBill = new OmsReceiptBill();
updateBill.setId(receiptBill.getId());
updateBill.setApproveStatus(ApproveStatusEnum.APPROVE_COMPLETE.getCode());
updateBill.setApproveTime(DateUtils.getNowDate());
updateBill.setReceiptStatus(OmsReceiptBill.ReceiptStatusEnum.REFUNDED.getCode());
omsReceiptBillMapper.update(updateBill);
List<OmsReceivableReceiptDetail> omsReceivableReceiptDetailList = omsReceivableReceiptDetailService.listByReceiptBillCode(receiptBill.getReceiptBillCode());
receivableBillService.updateReceiptAmount(omsReceivableReceiptDetailList.stream().map(OmsReceivableReceiptDetail::getReceivableBillId).collect(Collectors.toList()));
}
}
return TodoCommonTemplate.super.todoApproveCallback(todo);
}
@Override
public boolean multiInstanceApproveCallback(String activityName, ProcessInstance processInstance) {
return TodoCommonTemplate.super.multiInstanceApproveCallback(activityName, processInstance);
}
} }

View File

@ -2,6 +2,7 @@ package com.ruoyi.sip.service.impl;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
@ -144,10 +145,17 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
@Override @Override
public OmsReceivableBill query(Long id) { public OmsReceivableBill query(Long id) {
OmsReceivableBill omsReceivableBill = omsReceivableBillMapper.selectOmsReceivableBillById(id); OmsReceivableBill omsReceivableBill = omsReceivableBillMapper.selectOmsReceivableBillById(id);
List<OmsReceivableReceiptDetail> detailList = detailService.listByReceivableBillId(id);
omsReceivableBill.setDetailList(detailList); if (omsReceivableBill != null) {
List<OmsReceivableInvoiceDetail> omsReceivableInvoiceDetails = invoiceDetailService.listByReceivableBillId(id); List<OmsReceivableReceiptDetail> detailList = detailService.listByReceivableBillId(id);
omsReceivableBill.setInvoiceDetailList(omsReceivableInvoiceDetails); omsReceivableBill.setDetailList(detailList);
List<OmsReceivableInvoiceDetail> omsReceivableInvoiceDetails = invoiceDetailService.listByReceivableBillId(id);
omsReceivableBill.setInvoiceDetailList(omsReceivableInvoiceDetails);
List<OmsReceiptBill> receiptBills = receiptBillService.listRemainingAmountByPartnerCodeList(Collections.singletonList(omsReceivableBill.getPartnerCode()));
Map<String, BigDecimal> decimalMap = receiptBills.stream().filter(item -> item.getRemainingAmount() != null)
.collect(Collectors.toMap(OmsReceiptBill::getPartnerCode, OmsReceiptBill::getRemainingAmount, BigDecimal::add));
omsReceivableBill.setRemainingAmount(decimalMap.getOrDefault(omsReceivableBill.getPartnerCode(), BigDecimal.ZERO));
}
return omsReceivableBill; return omsReceivableBill;
} }
@ -159,7 +167,7 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
if (CollUtil.isEmpty(dto.getReceivableBills())) { if (CollUtil.isEmpty(dto.getReceivableBills())) {
return 0; return 0;
} }
Date minPlanDate=DateUtils.getNowDate();
// Fetch bills once // Fetch bills once
for (ReceivableOrderReceiptDto order : dto.getReceivableBills()) { for (ReceivableOrderReceiptDto order : dto.getReceivableBills()) {
BigDecimal taxRate = order.getTaxRate(); BigDecimal taxRate = order.getTaxRate();
@ -168,6 +176,7 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
taxRate = new BigDecimal(defaultTax); taxRate = new BigDecimal(defaultTax);
} }
for (OmsReceivableReceiptPlan plan : order.getReceiptPlans()) { for (OmsReceivableReceiptPlan plan : order.getReceiptPlans()) {
minPlanDate=minPlanDate.after(plan.getPlanReceiptDate())?plan.getPlanReceiptDate():minPlanDate;
// 计算每个 plan 的未税金额 = planAmount / (1 + 税率),保留两位小数 // 计算每个 plan 的未税金额 = planAmount / (1 + 税率),保留两位小数
// 计算未税金额 = planAmount / (1 + 税率) // 计算未税金额 = planAmount / (1 + 税率)
BigDecimal divisor = BigDecimal.ONE.add(taxRate); BigDecimal divisor = BigDecimal.ONE.add(taxRate);
@ -182,7 +191,7 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
receiptBill.setReceiptBillType(OmsReceiptBill.ReceiptBillTypeEnum.FROM_RECEIVABLE.getCode()); receiptBill.setReceiptBillType(OmsReceiptBill.ReceiptBillTypeEnum.FROM_RECEIVABLE.getCode());
receiptBill.setPartnerCode(firstReceivableBill.getPartnerCode()); receiptBill.setPartnerCode(firstReceivableBill.getPartnerCode());
receiptBill.setPartnerName(firstReceivableBill.getPartnerName()); receiptBill.setPartnerName(firstReceivableBill.getPartnerName());
receiptBill.setReceiptTime(dto.getEstimatedReceiptTime()); receiptBill.setReceiptTime(dto.getEstimatedReceiptTime()==null?minPlanDate:dto.getEstimatedReceiptTime());
receiptBill.setTotalPriceWithTax(dto.getTotalMergeReceiptAmount()); receiptBill.setTotalPriceWithTax(dto.getTotalMergeReceiptAmount());
receiptBill.setTotalPriceWithoutTax(totalWithoutTax); receiptBill.setTotalPriceWithoutTax(totalWithoutTax);
receiptBill.setTaxAmount(dto.getTotalMergeReceiptAmount().subtract(totalWithoutTax)); receiptBill.setTaxAmount(dto.getTotalMergeReceiptAmount().subtract(totalWithoutTax));
@ -268,20 +277,13 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
} }
List<OmsReceivableInvoiceDetail> invoiceDetails = invoiceDetailService.listByReceivableBillIdList(idList); List<OmsReceivableInvoiceDetail> invoiceDetails = invoiceDetailService.listByReceivableBillIdList(idList);
Map<Long, Map<Long, OmsReceivableInvoiceDetail>> planMap = invoiceDetails.stream().collect(Collectors.groupingBy( Map<Long, List< OmsReceivableInvoiceDetail>> receivableInvoiceDetailMap = invoiceDetails.stream().collect(Collectors.groupingBy(OmsReceivableInvoiceDetail::getReceivableBillId ));
OmsReceivableInvoiceDetail::getReceivableBillId,
Collectors.toMap(
OmsReceivableInvoiceDetail::getInvoicePlanId,
Function.identity(),
(d1, d2) -> d1.getCreateTime().after(d2.getCreateTime()) ? d1 : d2
)
));
for (OmsReceivableBill bill : bills) { for (OmsReceivableBill bill : bills) {
Map<Long, OmsReceivableInvoiceDetail> paymentDetailMap = List<OmsReceivableInvoiceDetail> detailList =
planMap.getOrDefault(bill.getId(), Collections.emptyMap()); receivableInvoiceDetailMap.getOrDefault(bill.getId(), Collections.emptyList());
if (CollUtil.isNotEmpty(paymentDetailMap)) { if (CollUtil.isNotEmpty(detailList)) {
Map<String, BigDecimal> amountMap = Map<String, BigDecimal> amountMap =
paymentDetailMap.values().stream() detailList.stream()
.filter(d -> d.getInvoiceAmount() != null) .filter(d -> d.getInvoiceAmount() != null)
.collect(Collectors.toMap( .collect(Collectors.toMap(
OmsReceivableInvoiceDetail::getInvoiceStatus, OmsReceivableInvoiceDetail::getInvoiceStatus,
@ -292,7 +294,8 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
BigDecimal paidAmount = amountMap BigDecimal paidAmount = amountMap
.getOrDefault(OmsInvoiceBill.InvoiceStatusEnum.INVOICE.getCode(), BigDecimal.ZERO) .getOrDefault(OmsInvoiceBill.InvoiceStatusEnum.INVOICE.getCode(), BigDecimal.ZERO)
.add(amountMap.getOrDefault( .add(amountMap.getOrDefault(
OmsInvoiceBill.InvoiceStatusEnum.RED_RUSH.getCode(), BigDecimal.ZERO)); OmsInvoiceBill.InvoiceStatusEnum.RED_RUSH.getCode(), BigDecimal.ZERO))
.subtract(amountMap.getOrDefault( OmsInvoiceBill.InvoiceStatusEnum.WAIT_RED_RUSH.getCode(), BigDecimal.ZERO));
BigDecimal waitPayAmount = BigDecimal waitPayAmount =
amountMap.getOrDefault( amountMap.getOrDefault(
@ -315,7 +318,7 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
if (CollUtil.isEmpty(dto.getReceivableBills())) { if (CollUtil.isEmpty(dto.getReceivableBills())) {
return 0; return 0;
} }
Date minPlanDate=DateUtils.getNowDate();
// Fetch bills once // Fetch bills once
for (ReceivableOrderInvoiceDto order : dto.getReceivableBills()) { for (ReceivableOrderInvoiceDto order : dto.getReceivableBills()) {
@ -327,7 +330,7 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
order.setTaxRate(taxRate); order.setTaxRate(taxRate);
for (OmsReceivableInvoicePlan plan : order.getInvoicePlans()) { for (OmsReceivableInvoicePlan plan : order.getInvoicePlans()) {
// 计算每个 plan 的未税金额 = planAmount / (1 + 税率),保留两位小数 // 计算每个 plan 的未税金额 = planAmount / (1 + 税率),保留两位小数
minPlanDate = minPlanDate.after(plan.getPlanInvoiceDate()) ? plan.getPlanInvoiceDate() : minPlanDate;
// 计算未税金额 = planAmount / (1 + 税率) // 计算未税金额 = planAmount / (1 + 税率)
BigDecimal divisor = BigDecimal.ONE.add(taxRate); BigDecimal divisor = BigDecimal.ONE.add(taxRate);
BigDecimal planWithoutTax = plan.getPlanAmount().divide(divisor, 2, java.math.RoundingMode.HALF_UP); BigDecimal planWithoutTax = plan.getPlanAmount().divide(divisor, 2, java.math.RoundingMode.HALF_UP);
@ -339,7 +342,7 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
OmsInvoiceBill invoiceBill = new OmsInvoiceBill(); OmsInvoiceBill invoiceBill = new OmsInvoiceBill();
OmsReceivableBill firstReceivableBill = selectOmsReceivableBillById(dto.getReceivableBills().get(0).getId()); OmsReceivableBill firstReceivableBill = selectOmsReceivableBillById(dto.getReceivableBills().get(0).getId());
invoiceBill.setInvoiceBillType(dto.getInvoiceBillType()); invoiceBill.setInvoiceBillType(dto.getInvoiceBillType());
invoiceBill.setInvoiceTime(dto.getInvoiceTime()); invoiceBill.setInvoiceTime(dto.getInvoiceTime()==null?minPlanDate:dto.getInvoiceTime());
invoiceBill.setPartnerCode(firstReceivableBill.getPartnerCode()); invoiceBill.setPartnerCode(firstReceivableBill.getPartnerCode());
invoiceBill.setPartnerName(firstReceivableBill.getPartnerName()); invoiceBill.setPartnerName(firstReceivableBill.getPartnerName());
invoiceBill.setTotalPriceWithTax(dto.getTotalMergeInvoiceAmount()); invoiceBill.setTotalPriceWithTax(dto.getTotalMergeInvoiceAmount());
@ -438,21 +441,14 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
List<OmsReceivableReceiptDetail> omsReceivableReceiptDetailList = detailService.listByReceivableBillIdList(idList); List<OmsReceivableReceiptDetail> omsReceivableReceiptDetailList = detailService.listByReceivableBillIdList(idList);
Map<Long, Map<Long, OmsReceivableReceiptDetail>> planMap = omsReceivableReceiptDetailList.stream().collect(Collectors.groupingBy( Map<Long, List<OmsReceivableReceiptDetail>> receiverableReceiptDetailMap = omsReceivableReceiptDetailList.stream().collect(Collectors.groupingBy(OmsReceivableReceiptDetail::getReceivableBillId ));
OmsReceivableReceiptDetail::getReceivableBillId,
Collectors.toMap(
OmsReceivableReceiptDetail::getReceiptPlanId,
Function.identity(),
(d1, d2) -> d1.getCreateTime().after(d2.getCreateTime()) ? d1 : d2
)
));
for (OmsReceivableBill bill : receivableBills) { for (OmsReceivableBill bill : receivableBills) {
Map<Long, OmsReceivableReceiptDetail> paymentDetailMap = List< OmsReceivableReceiptDetail> detailList =
planMap.getOrDefault(bill.getId(), Collections.emptyMap()); receiverableReceiptDetailMap.getOrDefault(bill.getId(), Collections.emptyList());
if (CollUtil.isNotEmpty(paymentDetailMap)) { if (CollUtil.isNotEmpty(detailList)) {
Map<String, BigDecimal> amountMap = Map<String, BigDecimal> amountMap =
paymentDetailMap.values().stream() detailList.stream()
.filter(d -> d.getReceiptAmount() != null) .filter(d -> d.getReceiptAmount() != null)
.collect(Collectors.toMap( .collect(Collectors.toMap(
OmsReceivableReceiptDetail::getReceiptStatus, OmsReceivableReceiptDetail::getReceiptStatus,
@ -463,11 +459,12 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
BigDecimal paidAmount = amountMap BigDecimal paidAmount = amountMap
.getOrDefault(OmsReceiptBill.ReceiptStatusEnum.PAYMENT.getCode(), BigDecimal.ZERO) .getOrDefault(OmsReceiptBill.ReceiptStatusEnum.PAYMENT.getCode(), BigDecimal.ZERO)
.add(amountMap.getOrDefault( .add(amountMap.getOrDefault(
OmsReceiptBill.ReceiptStatusEnum.REFUNDED.getCode(), BigDecimal.ZERO)); OmsReceiptBill.ReceiptStatusEnum.REFUNDED.getCode(), BigDecimal.ZERO))
//减去等待退款的数据 因为退款是负数
.subtract(amountMap.getOrDefault( OmsReceiptBill.ReceiptStatusEnum.WAIT_REFUNDED.getCode(), BigDecimal.ZERO));
BigDecimal waitPayAmount = BigDecimal waitPayAmount =
amountMap.getOrDefault( amountMap.getOrDefault(OmsReceiptBill.ReceiptStatusEnum.WAIT_PAYMENT.getCode(), BigDecimal.ZERO);
OmsReceiptBill.ReceiptStatusEnum.WAIT_PAYMENT.getCode(), BigDecimal.ZERO);
bill.setReceivedAmount(paidAmount); bill.setReceivedAmount(paidAmount);
bill.setUnreceivedAmount(bill.getTotalPriceWithTax() .subtract(paidAmount) bill.setUnreceivedAmount(bill.getTotalPriceWithTax() .subtract(paidAmount)
.subtract(waitPayAmount)); .subtract(waitPayAmount));

View File

@ -119,7 +119,7 @@ public class OmsReceivableReceiptDetailServiceImpl implements IOmsReceivableRece
omsFinAttachment.setRelatedBillType(OmsFinAttachment.RelatedBillTypeEnum.RECEIPT.getCode()); omsFinAttachment.setRelatedBillType(OmsFinAttachment.RelatedBillTypeEnum.RECEIPT.getCode());
omsFinAttachment.setDelFlag("0"); omsFinAttachment.setDelFlag("0");
List<OmsFinAttachment> attachmentList = finAttachmentService.selectOmsFinAttachmentList(omsFinAttachment); List<OmsFinAttachment> attachmentList = finAttachmentService.selectOmsFinAttachmentList(omsFinAttachment);
Map<Long, OmsFinAttachment> collect = attachmentList.stream().collect(Collectors.toMap(OmsFinAttachment::getRelatedBillId, Function.identity())); Map<Long, OmsFinAttachment> collect = attachmentList.stream().collect(Collectors.toMap(OmsFinAttachment::getRelatedBillId, Function.identity(),(v1,v2)->v1.getCreateTime().after(v2.getCreateTime())?v1:v2));
for (OmsReceivableReceiptDetail payablePaymentDetail : list) { for (OmsReceivableReceiptDetail payablePaymentDetail : list) {
payablePaymentDetail.setFinAttachment(collect.get(payablePaymentDetail.getReceiptBillId())); payablePaymentDetail.setFinAttachment(collect.get(payablePaymentDetail.getReceiptBillId()));
} }
@ -224,4 +224,9 @@ public class OmsReceivableReceiptDetailServiceImpl implements IOmsReceivableRece
omsReceivableReceiptDetail.setReceiptPlanIdList(planIdList); omsReceivableReceiptDetail.setReceiptPlanIdList(planIdList);
return omsReceivableReceiptDetailMapper.list(omsReceivableReceiptDetail); return omsReceivableReceiptDetailMapper.list(omsReceivableReceiptDetail);
} }
@Override
public void deleteByBillCode(String receiptBillCode) {
omsReceivableReceiptDetailMapper.deleteByBillCode(receiptBillCode);
}
} }

View File

@ -83,7 +83,9 @@ public class OmsReceivableReceiptPlanServiceImpl implements IOmsReceivableReceip
for (OmsReceivableReceiptPlan omsReceivableReceiptPlan : omsReceivableReceiptPlans) { for (OmsReceivableReceiptPlan omsReceivableReceiptPlan : omsReceivableReceiptPlans) {
//找到最新的一条数据 如果不是退款 那么不允许再次勾选 //找到最新的一条数据 如果不是退款 那么不允许再次勾选
OmsReceivableReceiptDetail omsReceivableReceiptDetail = detailMap.get(omsReceivableReceiptPlan.getId()); OmsReceivableReceiptDetail omsReceivableReceiptDetail = detailMap.get(omsReceivableReceiptPlan.getId());
if (omsReceivableReceiptDetail != null && !OmsReceivableReceiptDetail.ReceivableDetailTypeEnum.REFUND.getCode().equalsIgnoreCase(omsReceivableReceiptDetail.getReceivableDetailType())) if (omsReceivableReceiptDetail != null &&
!(OmsReceivableReceiptDetail.ReceivableDetailTypeEnum.REFUND.getCode().equalsIgnoreCase(omsReceivableReceiptDetail.getReceivableDetailType())
&& omsReceivableReceiptDetail.getReceiptStatus().equals(OmsReceiptBill.ReceiptStatusEnum.REFUNDED.getCode())))
omsReceivableReceiptPlan.setDetailId(omsReceivableReceiptDetail.getId()); omsReceivableReceiptPlan.setDetailId(omsReceivableReceiptDetail.getId());
} }
} }

View File

@ -40,7 +40,7 @@
select select
t1.id, t1.receipt_bill_code, t1.receipt_bill_type, t1.receipt_time, t1.actual_receipt_time, t1.partner_code, t1.id, t1.receipt_bill_code, t1.receipt_bill_type, t1.receipt_time, t1.actual_receipt_time, t1.partner_code,
t1.order_code, t1.total_price_with_tax, t1.total_price_without_tax, t1.tax_amount, t1.create_by, t1.create_time, t1.update_by, t1.update_time, t1.remark, t1.del_flag, t1.project_code, t1.project_name, t1.receipt_status, t1.approve_status, t1.approve_node, t1.approve_time, t1.receipt_method, t1.receipt_account_name, t1.receipt_bank_number, t1.receipt_bank_open_address, t1.bank_number, t1.refund_status, t1.order_code, t1.total_price_with_tax, t1.total_price_without_tax, t1.tax_amount, t1.create_by, t1.create_time, t1.update_by, t1.update_time, t1.remark, t1.del_flag, t1.project_code, t1.project_name, t1.receipt_status, t1.approve_status, t1.approve_node, t1.approve_time, t1.receipt_method, t1.receipt_account_name, t1.receipt_bank_number, t1.receipt_bank_open_address, t1.bank_number, t1.refund_status,
t1.remaining_amount,t2.partner_name t1.remaining_amount,t2.partner_name,t1.original_bill_id
from oms_receipt_bill t1 from oms_receipt_bill t1
left join partner_info t2 on t1.partner_code=t2.partner_code left join partner_info t2 on t1.partner_code=t2.partner_code
</sql> </sql>
@ -57,6 +57,31 @@
<if test="receiptBillCode != null and receiptBillCode != ''"> <if test="receiptBillCode != null and receiptBillCode != ''">
and t1.receipt_bill_code = #{receiptBillCode} and t1.receipt_bill_code = #{receiptBillCode}
</if> </if>
<if test="projectCode != null and projectCode != ''">
and t1.receipt_bill_code in (
select t1.receipt_bill_code from oms_payable_ticket_detail t1
inner join oms_payable_bill t2 on t1.payable_bill_id=t2.id
inner join project_order_info t3 on t2.order_code=t3.order_code
inner join project_info t4 on t3.project_id=t4.id
where t4.project_code = #{projectCode}
)
</if>
<if test="projectName != null and projectName != ''">
and t1.receipt_bill_code in (
select t1.receipt_bill_code from oms_payable_ticket_detail t1
inner join oms_payable_bill t2 on t1.payable_bill_id=t2.id
inner join project_order_info t3 on t2.order_code=t3.order_code
inner join project_info t4 on t3.project_id=t4.id
where t4.project_name like concat('%',#{projectName},'%')
)
</if>
<if test="receivableBillCode != null and receivableBillCode != ''">
t1.receipt_bill_code in (
select receipt_bill_code from oms_receivable_receipt_detail orrd
left join oms_receivable_bill orb on orrd.receivable_bill_id=orb.ID
where orb.receivable_bill_code=#{receivableBillCode}
)
</if>
<if test="receiptBillCodeList != null and receiptBillCodeList != ''"> <if test="receiptBillCodeList != null and receiptBillCodeList != ''">
and t1.receipt_bill_code in and t1.receipt_bill_code in
<foreach collection="receiptBillCodeList" item="item" separator="," open="(" close=")"> <foreach collection="receiptBillCodeList" item="item" separator="," open="(" close=")">
@ -86,6 +111,9 @@
<if test="partnerCode != null and partnerCode != ''"> <if test="partnerCode != null and partnerCode != ''">
and t1.partner_code = #{partnerCode} and t1.partner_code = #{partnerCode}
</if> </if>
<if test="partnerName != null and partnerName != ''">
and t1.partner_name = #{partnerName}
</if>
<if test="orderCode != null and orderCode != ''"> <if test="orderCode != null and orderCode != ''">
and t1.order_code = #{orderCode} and t1.order_code = #{orderCode}
</if> </if>
@ -116,12 +144,6 @@
<if test="delFlag != null and delFlag != ''"> <if test="delFlag != null and delFlag != ''">
and t1.del_flag = #{delFlag} and t1.del_flag = #{delFlag}
</if> </if>
<if test="projectCode != null and projectCode != ''">
and t1.project_code = #{projectCode}
</if>
<if test="projectName != null and projectName != ''">
and t1.project_name = #{projectName}
</if>
<if test="receiptStatus != null and receiptStatus != ''"> <if test="receiptStatus != null and receiptStatus != ''">
and t1.receipt_status = #{receiptStatus} and t1.receipt_status = #{receiptStatus}
</if> </if>
@ -129,7 +151,11 @@
and t1.approve_status = #{approveStatus} and t1.approve_status = #{approveStatus}
</if> </if>
<if test="approveNode != null and approveNode != ''"> <if test="approveNode != null and approveNode != ''">
and t1.approve_node = #{approveNode} and t1.receipt_bill_code in
(
select business_key from bu_todo where approve_user_name like concat('%', #{approveNode}, '%') and process_key in (
'finance_ticket_refound','fianance_ticket')
)
</if> </if>
<if test="approveTime != null"> <if test="approveTime != null">
and t1.approve_time = #{approveTime} and t1.approve_time = #{approveTime}
@ -152,43 +178,56 @@
<if test="refundStatus != null and refundStatus != ''"> <if test="refundStatus != null and refundStatus != ''">
and t1.refund_status = #{refundStatus} and t1.refund_status = #{refundStatus}
</if> </if>
<if test="(params.beginApproveTime != null and params.beginApproveTime != '') or (params.endApproveTime != null and params.endApproveTime!='')">
<choose>
<when test="(params.beginApproveTime != null and params.beginApproveTime != '') and (params.endApproveTime != null and params.endApproveTime!='')">
and t1.approve_time between #{params.beginApproveTime} and #{params.endApproveTime}
</when>
<when test="(params.beginApproveTime != null and params.beginApproveTime != '')">
and t1.approve_time <![CDATA[ >= ]]> #{params.beginApproveTime}
</when>
<when test="(params.endApproveTime != null and params.endApproveTime!='')">
and t1.approve_time <![CDATA[ <= ]]> #{params.endApproveTime}
</when>
</choose>
</if>
<if test="(params.beginPlanReceiveTime != null and params.beginPlanReceiveTime != '') or (params.endPlanReceiveTime != null and params.endPlanReceiveTime!='')">
<choose>
<when test="(params.beginPlanReceiveTime != null and params.beginPlanReceiveTime != '') and (params.endPlanReceiveTime != null and params.endPlanReceiveTime!='')">
and t1.receipt_time between #{params.beginPlanReceiveTime} and #{params.endPlanReceiveTime}
</when>
<when test="(params.beginPlanReceiveTime != null and params.beginPlanReceiveTime != '')">
and t1.receipt_time <![CDATA[ >= ]]> #{params.beginPlanReceiveTime}
</when>
<when test="(params.endPlanReceiveTime != null and params.endPlanReceiveTime!='')">
and t1.receipt_time <![CDATA[ <= ]]> #{params.endPlanReceiveTime}
</when>
</choose>
</if>
<if test="(params.beginActualReceiveTime != null and params.beginActualReceiveTime != '') or (params.endActualReceiveTime != null and params.endActualReceiveTime!='')">
<choose>
<when test="(params.beginActualReceiveTime != null and params.beginActualReceiveTime != '') and (params.endActualReceiveTime != null and params.endActualReceiveTime!='')">
and t1.actual_receipt_time between #{params.beginActualReceiveTime} and #{params.endActualReceiveTime}
</when>
<when test="(params.beginActualReceiveTime != null and params.beginActualReceiveTime != '')">
and t1.actual_receipt_time <![CDATA[ >= ]]> #{params.beginActualReceiveTime}
</when>
<when test="(params.endActualReceiveTime != null and params.endActualReceiveTime!='')">
and t1.actual_receipt_time <![CDATA[ <= ]]> #{params.endActualReceiveTime}
</when>
</choose>
</if>
</where> </where>
</select> </select>
<!--根据ID查详情--> <!--根据ID查详情-->
<select id="queryById" parameterType="Long" resultMap="OmsReceiptBillMap"> <select id="queryById" parameterType="Long" resultMap="OmsReceiptBillMap">
SELECT id, <include refid="selectReceiptBillVo"/>
receipt_bill_code, WHERE t1.id = #{id}
receipt_bill_type,
receipt_time,
actual_receipt_time,
partner_code,
order_code,
total_price_with_tax,
total_price_without_tax,
tax_amount,
create_by,
create_time,
update_by,
update_time,
remark,
del_flag,
project_code,
project_name,
receipt_status,
approve_status,
approve_node,
approve_time,
receipt_method,
receipt_account_name,
receipt_bank_number,
receipt_bank_open_address,
bank_number,
refund_status,
remaining_amount
FROM oms_receipt_bill
WHERE id = #{id}
LIMIT 1 LIMIT 1
</select> </select>
<select id="selectMaxCodeByPrefix" resultType="java.lang.Integer"> <select id="selectMaxCodeByPrefix" resultType="java.lang.Integer">
@ -214,6 +253,98 @@
receipt_bill_code = #{receiptBillCode} receipt_bill_code = #{receiptBillCode}
</where> </where>
</select> </select>
<select id="listApprove" resultType="com.ruoyi.sip.domain.OmsReceiptBill">
select
t1.id, t1.receipt_bill_code, t1.receipt_bill_type, t1.receipt_time, t1.actual_receipt_time, t1.partner_code,
t1.order_code, t1.total_price_with_tax, t1.total_price_without_tax, t1.tax_amount, t1.create_by, t1.create_time, t1.update_by, t1.update_time, t1.remark, t1.del_flag, t1.project_code, t1.project_name, t1.receipt_status, t1.approve_status, t1.approve_node, t1.approve_time, t1.receipt_method, t1.receipt_account_name, t1.receipt_bank_number, t1.receipt_bank_open_address, t1.bank_number, t1.refund_status,
t1.remaining_amount,t2.partner_name
${flowRelationDto.querySql}
from oms_receipt_bill t1
left join partner_info t2 on t1.partner_code=t2.partner_code
${flowRelationDto.joinSql}
<where>
<if test="entity.id != null">
and t1.id = #{entity.id}
</if>
<if test="entity.receiptBillCode != null and entity.receiptBillCode != ''">
and t1.receipt_bill_code = #{entity.receiptBillCode}
</if>
<if test="entity.projectCode != null and entity.projectCode != ''">
and t1.receipt_bill_code in (
select t1.receipt_bill_code from oms_payable_ticket_detail t1
inner join oms_payable_bill t2 on t1.payable_bill_id=t2.id
inner join project_order_info t3 on t2.order_code=t3.order_code
inner join project_info t4 on t3.project_id=t4.id
where t4.project_code = #{entity.projectCode}
)
</if>
<if test="entity.projectName != null and entity.projectName != ''">
and t1.receipt_bill_code in (
select t1.receipt_bill_code from oms_payable_ticket_detail t1
inner join oms_payable_bill t2 on t1.payable_bill_id=t2.id
inner join project_order_info t3 on t2.order_code=t3.order_code
inner join project_info t4 on t3.project_id=t4.id
where t4.project_name like concat('%',#{entity.projectName},'%')
)
</if>
<if test="entity.receivableBillCode != null and entity.receivableBillCode != ''">
t1.receipt_bill_code in (
select receipt_bill_code from oms_receivable_receipt_detail orrd
left join oms_receivable_bill orb on orrd.receivable_bill_id=orb.ID
where orb.receivable_bill_code=#{entity.receivableBillCode}
)
</if>
<if test="entity.receiptBillCodeList != null and entity.receiptBillCodeList != ''">
and t1.receipt_bill_code in
<foreach collection="entity.receiptBillCodeList" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</if>
<if test="entity.remainingAmount != null and entity.remainingAmount != ''">
<choose>
<when test="entity.remainingAmount == -1">
and t1.remaining_amount != 0
</when>
<when test="entity.remainingAmount !== -1">
and t1.remaining_amount = #{entity.remainingAmount}
</when>
</choose>
</if>
<if test="entity.receiptBillType != null and entity.receiptBillType != ''">
and t1.receipt_bill_type = #{entity.receiptBillType}
</if>
<if test="entity.partnerCode != null and entity.partnerCode != ''">
and t1.partner_code = #{partnerCode}
</if>
<if test="entity.partnerName != null and entity.partnerName != ''">
and t1.partner_name = #{entity.partnerName}
</if>
<if test="entity.approveNode != null and entity.approveNode != ''">
and t1.receipt_bill_code in
(
select business_key from bu_todo where approve_user_name like concat('%', #{entity.approveNode}, '%') and process_key =#{entity.processKey}
)
</if>
<if test="(entity.params.beginApplyTime != null and entity.params.beginApplyTime != '') or (entity.params.endApplyTime != null and entity.params.endApplyTime!='')">
<choose>
<when test="(entity.params.beginApplyTime != null and entity.params.beginApplyTime != '') and (entity.params.endApplyTime != null and entity.params.endApplyTime!='')">
and t3.apply_time between #{entity.params.beginApplyTime} and #{entity.params.endApplyTime}
</when>
<when test="(entity.params.beginApplyTime != null and entity.params.beginApplyTime != '')">
and t3.apply_time <![CDATA[ >= ]]> #{entity.params.beginApplyTime}
</when>
<when test="(entity.params.endApplyTime != null and entity.params.endApplyTime!='')">
and t3.apply_time <![CDATA[ <= ]]> #{entity.params.endApplyTime}
</when>
</choose>
</if>
</where>
</select>
<!--新增所有列--> <!--新增所有列-->
@ -304,6 +435,9 @@
<if test="remainingAmount != null"> <if test="remainingAmount != null">
remaining_amount, remaining_amount,
</if> </if>
<if test="originalBillId != null">
original_bill_id,
</if>
</trim> </trim>
<trim prefix="values (" suffix=")" suffixOverrides=","> <trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="receiptBillCode != null and receiptBillCode != ''"> <if test="receiptBillCode != null and receiptBillCode != ''">
@ -390,6 +524,9 @@
<if test="remainingAmount != null"> <if test="remainingAmount != null">
#{remainingAmount}, #{remainingAmount},
</if> </if>
<if test="originalBillId != null">
#{originalBillId},
</if>
</trim> </trim>
</insert> </insert>
@ -493,6 +630,14 @@
where id = #{item.id} where id = #{item.id}
</foreach> </foreach>
</update> </update>
<update id="revoke">
update oms_receipt_bill
set approve_status = #{approveStatus},
approve_time =null,
remaining_amount=null,
update_time=now()
where id = #{id}
</update>
<!--通过主键删除--> <!--通过主键删除-->
<delete id="deleteById"> <delete id="deleteById">

View File

@ -52,7 +52,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.update_time t1.update_time
from oms_payable_payment_plan t1 from oms_payable_payment_plan t1
left join oms_payable_payment_detail t2 on t1.id = t2.payment_plan_id left join oms_payable_payment_detail t2 on t1.id = t2.payment_plan_id
where t2.id is null and t1.payable_bill_id = #{payableBillId} left join oms_payment_bill t3 on t2.payment_bill_code=t3.payment_bill_code
where (t2.id is null or t3.payment_status='-1') and t1.payable_bill_id = #{payableBillId}
order by plan_payment_date order by plan_payment_date
limit 1 limit 1
</select> </select>

View File

@ -60,7 +60,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.update_time t1.update_time
from oms_payable_ticket_plan t1 from oms_payable_ticket_plan t1
left join oms_payable_ticket_detail t2 on t1.id=t2.ticket_plan_id left join oms_payable_ticket_detail t2 on t1.id=t2.ticket_plan_id
where t2.id is null and t1.payable_bill_id=#{payableBillId} left join oms_ticket_bill t3 on t2.ticket_bill_code =t3.ticket_bill_code
where (t2.id is null or t3.ticket_status='-1') and t1.payable_bill_id=#{payableBillId}
order by t1.plan_ticket_date order by t1.plan_ticket_date
limit 1 limit 1
</select> </select>

View File

@ -116,18 +116,49 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
, t1.status, t1.approve_status, t1.approve_time, t1.approve_node, t1.confirm_status, t1.create_time, t1.update_time, t1.del_flag,t1.version , t1.status, t1.approve_status, t1.approve_time, t1.approve_node, t1.confirm_status, t1.create_time, t1.update_time, t1.del_flag,t1.version
, t1.file_id , t1.file_id
,t2.vendor_name,t2.vendor_user,t2.vendor_phone ,t2.vendor_name,t2.vendor_user,t2.vendor_phone
,t3.apply_time,t3.process_key,t3.todo_id,t3.task_id
<if test="'bu_todo_completed'.equals(tableName)"> <choose>
,t3.approve_time as todo_approve_time <when test="'bu_todo'.equals(tableName)">
</if> ,t3.apply_time,t3.process_key,t3.todo_id,t3.task_id
</when>
<when test="'bu_todo_completed'.equals(tableName)">
,t3.apply_time,t3.approve_time as todo_approve_time,t3.process_key
</when>
</choose>
from oms_purchase_order t1 from oms_purchase_order t1
left join oms_vendor_info t2 on t1.vendor_id = t2.vendor_id left join oms_vendor_info t2 on t1.vendor_id = t2.vendor_id
inner join ${tableName} t3 on (t3.process_key in ('purchase_order_online') and t3.approve_user=#{entity.approveUser} and t3.task_name!='商务' and t3.business_key=t1.purchase_no) inner join
<choose>
<when test="'bu_todo'.equals(tableName)">
(select bt.business_key,bt.apply_time,bt.process_key,bt.todo_id,bt.task_id from bu_todo bt
WHERE
bt.process_key IN ('purchase_order_online')
AND bt.approve_user = #{entity.approveUser}
AND bt.task_name!='商务'
)
</when>
<when test="'bu_todo_completed'.equals(tableName)">
(SELECT
business_key,
max(btc.approve_time) approve_time,
max(btc.apply_time) apply_time,
max(btc.process_key) process_key
FROM
bu_todo_completed btc
WHERE
btc.process_key IN ('purchase_order_online')
AND btc.approve_user = #{entity.approveUser}
AND btc.task_name!='商务'
GROUP BY business_key)
</when>
</choose>
t3 on t3.business_key=t1.purchase_no
<where> <where>
<if test="entity.purchaseNo != null and entity.purchaseNo != ''"> and t1.purchase_no = #{entity.purchaseNo}</if> <if test="entity.purchaseNo != null and entity.purchaseNo != ''"> and t1.purchase_no = #{entity.purchaseNo}</if>
<if test="entity.vendorName != null "> and t2.vendor_name = #{entity.vendorName}</if> <if test="entity.vendorName != null "> and t2.vendor_name = #{entity.vendorName}</if>
<if test="entity.ownerName != null "> and t1.owner_name = #{entity.ownerName}</if> <if test="entity.ownerName != null "> and t1.owner_name = #{entity.ownerName}</if>
<if test="entity.approveUser != null "> and t3.approve_user = #{entity.approveUser}</if> <!-- <if test="entity.approveUser != null "> and t3.approve_user = #{entity.approveUser}</if>-->
<if test="entity.params.applyTimeStart != null and entity.params.applyTimeEnd != ''"> <if test="entity.params.applyTimeStart != null and entity.params.applyTimeEnd != ''">
<choose> <choose>
<when test="entity.params.applyTimeStart != null and entity.params.applyTimeEnd != null"> <when test="entity.params.applyTimeStart != null and entity.params.applyTimeEnd != null">

View File

@ -64,6 +64,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="inventoryCode != null and inventoryCode != ''"> and t1.inventory_code = #{inventoryCode}</if> <if test="inventoryCode != null and inventoryCode != ''"> and t1.inventory_code = #{inventoryCode}</if>
<if test="productType != null and productType != ''"> and t1.product_type = #{productType}</if> <if test="productType != null and productType != ''"> and t1.product_type = #{productType}</if>
<if test="createBy != null and createBy != ''"> and t1.create_by = #{createBy}</if> <if test="createBy != null and createBy != ''"> and t1.create_by = #{createBy}</if>
<if test="projectName != null and projectName != ''"> and t3.project_name like concat('%', #{projectName}, '%')</if>
<if test="(params.beginPlanReceiptDate != null and params.beginPlanReceiptDate != '') or (params.endPlanReceiptDate != null and params.endPlanReceiptDate!='')">
<choose>
<when test="(params.beginPlanReceiptDate != null and params.beginPlanReceiptDate != '') and (params.endPlanReceiptDate != null and params.endPlanReceiptDate!='')">
and t4.plan_receipt_date between #{params.beginPlanReceiptDate} and #{params.endPlanReceiptDate}
</when>
<when test="(params.beginPlanReceiptDate != null and params.beginPlanReceiptDate != '')">
and t4.plan_receipt_date <![CDATA[ >= ]]> #{params.beginPlanReceiptDate}
</when>
<when test="(params.endPlanReceiptDate != null and params.endPlanReceiptDate!='')">
and t4.plan_receipt_date <![CDATA[ <= ]]> #{params.endPlanReceiptDate}
</when>
</choose>
</if>
and t1.del_flag = '0' and t1.del_flag = '0'
</where> </where>
</select> </select>

View File

@ -42,7 +42,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.update_time t1.update_time
from oms_receivable_invoice_plan t1 from oms_receivable_invoice_plan t1
left join oms_receivable_invoice_detail t2 on t1.id=t2.invoice_plan_id left join oms_receivable_invoice_detail t2 on t1.id=t2.invoice_plan_id
where t2.id is null and t1.receivable_bill_id=#{payableBillId} left join oms_invoice_bill t3 on t2.invoice_bill_code=t3.invoice_bill_code
where (t2.id is null or t3.invoice_status='-1') and t1.receivable_bill_id=#{payableBillId}
order by t1.plan_invoice_date order by t1.plan_invoice_date
limit 1 limit 1

View File

@ -93,7 +93,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY t1.create_time DESC ORDER BY t1.create_time DESC
</select> </select>
<select id="listReceivableByReceiptBillCode" resultType="com.ruoyi.sip.domain.dto.ReceiptDetailDTO"> <select id="listReceivableByReceiptBillCode" resultType="com.ruoyi.sip.domain.dto.ReceiptDetailDTO">
select t1.receipt_amount, t2.receivable_bill_code, t4.project_name, t4.project_code, t2.total_price_with_tax select t1.receipt_amount, t2.receivable_bill_code, t4.project_name, t4.project_code, t2.total_price_with_tax,t2.product_type
from (SELECT sum(receipt_amount) receipt_amount, from (SELECT sum(receipt_amount) receipt_amount,
receivable_bill_id receivable_bill_id
FROM oms_receivable_receipt_detail FROM oms_receivable_receipt_detail
@ -213,4 +213,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{id} #{id}
</foreach> </foreach>
</delete> </delete>
<delete id="deleteByBillCode">
delete
from oms_receivable_receipt_detail
where receipt_bill_code = #{receiptBillCode}
</delete>
</mapper> </mapper>

View File

@ -55,7 +55,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.update_time t1.update_time
from oms_receivable_receipt_plan t1 from oms_receivable_receipt_plan t1
left join oms_receivable_receipt_detail t2 on t1.id = t2.receipt_plan_id left join oms_receivable_receipt_detail t2 on t1.id = t2.receipt_plan_id
where t2.id is null and t1.receivable_bill_id = #{receivableBillId} left join oms_receipt_bill t3 on t2.receipt_bill_code=t3.receipt_bill_code
where (t2.id is null or t3.receipt_status='-1') and t1.receivable_bill_id = #{receivableBillId}
order by plan_receipt_date order by plan_receipt_date
limit 1 limit 1
</select> </select>