feat(finance): 实现手工匹配核销功能

- 新增付款单与应付单的手工匹配核销界面
- 支持应付单和付款单的独立过滤查询
- 实现核销金额的实时计算与校验逻辑
- 添加应付计划选择弹窗及交互逻辑
- 集成税务相关金额的自动计算功能
- 提供核销明细数据的批量插入接口支持
- 优化表格展示与分页查询用户体验
dev_1.0.1
chenhao 2025-12-17 17:25:43 +08:00
parent 8d6ca0b64f
commit f79150abc9
23 changed files with 885 additions and 790 deletions

View File

@ -150,3 +150,23 @@ export function listPaymentApproved(query) {
}) })
} }
// 查询付款单列表 (核销专用)
export function listPaymentForWriteOff(query) {
return request({
url: '/finance/payment/write-off/list',
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: tansParams(query)
})
}
// 手工匹配核销
export function manualWriteOff(data) {
return request({
url: '/finance/writeoff',
method: 'post',
data: data
})
}

View File

@ -1,395 +0,0 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="120px">
<el-form-item label="制造商名称" prop="vendorName">
<el-input
v-model="queryParams.vendorName"
placeholder="请输入制造商名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="采购应付单编号" prop="payableBillCode">
<el-input
v-model="queryParams.payableBillCode"
placeholder="请输入采购应付单编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="采购付款单编号" prop="paymentCode">
<el-input
v-model="queryParams.paymentCode"
placeholder="请输入采购付款单编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="应付单生成时间">
<el-date-picker
v-model="payableDateRange"
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 label="付款单生成时间">
<el-date-picker
v-model="paymentDateRange"
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>
<div v-if="showTables">
<!-- 采购应付单表格 -->
<h3>采购应付单</h3>
<div class="table-summary" style="margin-bottom: 10px;">
<span style="font-weight: bold; margin-right: 20px;">应付单本次核销总额: <span style="color: #409EFF">{{ totalPayableWriteOffAmount.toFixed(2) }}</span></span>
</div>
<el-table v-loading="loadingPayable" :data="payableList" border>
<el-table-column label="采购应付单编号" align="center" prop="payableBillCode" width="150" show-overflow-tooltip/>
<el-table-column label="制造商名称" align="center" prop="vendorName" width="150" show-overflow-tooltip/>
<el-table-column label="本次核销金额" align="center" width="150">
<template slot-scope="scope">
<el-input
v-model="scope.row.currentWriteOffAmount"
placeholder="点击选择计划"
readonly
@click.native="handleOpenPlanSelector(scope.row)"
style="cursor: pointer;"
>
<i slot="suffix" class="el-input__icon el-icon-search"></i>
</el-input>
</template>
</el-table-column>
<el-table-column label="未核销金额" align="center" prop="unpaidAmount" width="120" />
<el-table-column label="未核销含税总价" align="center" prop="unpaidAmount" width="120">
<template slot-scope="scope">
{{ scope.row.unpaidAmount }}
</template>
</el-table-column>
<el-table-column label="未核销税额" align="center" width="120">
<template slot-scope="scope">
{{ calculateTax(scope.row.unpaidAmount, scope.row.taxRate) }}
</template>
</el-table-column>
<el-table-column label="已核销含税总价" align="center" prop="paidAmount" width="120" />
<el-table-column label="已核销未税总价" align="center" width="120">
<template slot-scope="scope">
{{ calculateExcludingTax(scope.row.paidAmount, scope.row.taxRate) }}
</template>
</el-table-column>
<el-table-column label="已核销税额" align="center" width="120">
<template slot-scope="scope">
{{ calculateTax(scope.row.paidAmount, scope.row.taxRate) }}
</template>
</el-table-column>
<el-table-column label="应付单生成时间" align="center" prop="createTime" width="160">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="payableTotal>0"
:total="payableTotal"
:page.sync="payableQueryParams.pageNum"
:limit.sync="payableQueryParams.pageSize"
@pagination="getPayableList"
/>
<!-- 采购付款单表格 -->
<h3 style="margin-top: 30px;">采购付款单</h3>
<div class="table-summary" style="margin-bottom: 10px;">
<span style="font-weight: bold; margin-right: 20px;">付款单本次核销总额: <span :style="{color: isWriteOffAmountValid ? '#67C23A' : '#F56C6C'}">{{ totalPaymentWriteOffAmount.toFixed(2) }}</span></span>
<span v-if="!isWriteOffAmountValid" style="color: #F56C6C; font-size: 12px;"><i class="el-icon-warning"></i> </span>
</div>
<el-table v-loading="loadingPayment" :data="paymentList" border>
<el-table-column label="采购付款单号" align="center" prop="paymentBillCode" width="150" show-overflow-tooltip/>
<el-table-column label="制造商名称" align="center" prop="vendorName" width="150" show-overflow-tooltip/>
<el-table-column label="本次核销含税总价" align="center" width="150">
<template slot-scope="scope">
<el-input-number
v-model="scope.row.currentWriteOffAmount"
:precision="2"
:step="100"
:min="0"
:max="scope.row.unWrittenAmount || scope.row.paymentAmount"
size="small"
style="width: 100%"
/>
</template>
</el-table-column>
<el-table-column label="未核销含税总价" align="center" width="120">
<template slot-scope="scope">
{{ scope.row.unWrittenAmount || scope.row.paymentAmount }} <!-- Assuming paymentAmount is total initially -->
</template>
</el-table-column>
<el-table-column label="未核销未税总价" align="center" width="120">
<template slot-scope="scope">
{{ calculateExcludingTax(scope.row.unWrittenAmount || scope.row.paymentAmount, 0) }} <!-- Payment usually doesn't have tax rate per se, using 0 or need logic -->
</template>
</el-table-column>
<el-table-column label="未核销税额" align="center" width="120">
<template slot-scope="scope">0.00</template> <!-- Placeholder if payment has no tax logic -->
</el-table-column>
<el-table-column label="已核销含税总价" align="center" prop="writtenAmount" width="120">
<template slot-scope="scope">{{ scope.row.writtenAmount || 0 }}</template>
</el-table-column>
<el-table-column label="已核销未税总价" align="center" width="120">
<template slot-scope="scope">
{{ calculateExcludingTax(scope.row.writtenAmount || 0, 0) }}
</template>
</el-table-column>
<el-table-column label="已核销税额" align="center" width="120">
<template slot-scope="scope">0.00</template>
</el-table-column>
<el-table-column label="付款单类型" align="center" prop="paymentBillType" width="120">
<template slot-scope="scope">
<dict-tag :options="dict.type.payment_bill_type" :value="scope.row.paymentBillType"/>
</template>
</el-table-column>
<el-table-column label="付款单生成时间" align="center" prop="createTime" width="160">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="paymentTotal>0"
:total="paymentTotal"
:page.sync="paymentQueryParams.pageNum"
:limit.sync="paymentQueryParams.pageSize"
@pagination="getPaymentList"
/>
</div>
<!-- 弹窗选择应付计划 -->
<el-dialog :title="planDialogTitle" :visible.sync="planDialogVisible" width="70%" append-to-body>
<payment-plan-selector
v-if="planDialogVisible"
ref="planSelector"
:payable-data="currentPayableRow"
:selected-plans="currentPayableRow ? currentPayableRow.selectedPlans : []"
:is-init-edit="false"
/>
<!-- Note: is-init-edit=false makes it read-only for editing plans generally, but we want to SELECT.
PaymentPlanSelector logic: 'selection-change' works.
If PaymentPlanSelector allows selection only in some mode, we need to check.
Looking at PaymentPlan.vue: <el-table ... @selection-change="selectPlan">
It seems selection is always enabled.
-->
<div slot="footer" class="dialog-footer">
<el-button @click="planDialogVisible = false"> </el-button>
<el-button type="primary" @click="handlePlanSelectionConfirm"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listPayable } from "@/api/finance/payable";
import { listPayment } from "@/api/finance/payment";
import PaymentPlanSelector from "../payable/components/PaymentPlan.vue";
export default {
name: "ManualWriteOff",
components: { PaymentPlanSelector },
dicts: ['payment_status', 'payment_bill_type'],
data() {
return {
//
loadingPayable: false,
loadingPayment: false,
//
showTables: false,
//
queryParams: {
vendorName: undefined,
payableBillCode: undefined,
paymentCode: undefined,
},
payableDateRange: [],
paymentDateRange: [],
//
payableList: [],
payableTotal: 0,
payableQueryParams: {
pageNum: 1,
pageSize: 10,
vendorName: undefined,
payableBillCode: undefined,
params: {}
},
//
paymentList: [],
paymentTotal: 0,
paymentQueryParams: {
pageNum: 1,
pageSize: 10,
vendorName: undefined,
paymentCode: undefined,
params: {}
},
//
planDialogVisible: false,
currentPayableRow: null,
planDialogTitle: "选择应付计划"
};
},
computed: {
totalPayableWriteOffAmount() {
return this.payableList.reduce((sum, row) => sum + (row.currentWriteOffAmount || 0), 0);
},
totalPaymentWriteOffAmount() {
return this.paymentList.reduce((sum, row) => sum + (row.currentWriteOffAmount || 0), 0);
},
isWriteOffAmountValid() {
// use a small epsilon for float comparison if needed, but direct comparison is usually okay for UI validation
return this.totalPaymentWriteOffAmount <= this.totalPayableWriteOffAmount + 0.01;
}
},
methods: {
/** 搜索按钮操作 */
handleQuery() {
if (!this.queryParams.vendorName) {
this.$modal.msgError("请输入制造商名称");
return;
}
this.showTables = true;
this.payableQueryParams.pageNum = 1;
this.paymentQueryParams.pageNum = 1;
this.syncParams();
this.getPayableList();
this.getPaymentList();
},
/** 重置按钮操作 */
resetQuery() {
this.payableDateRange = [];
this.paymentDateRange = [];
this.resetForm("queryForm");
this.showTables = false;
this.payableList = [];
this.paymentList = [];
},
syncParams() {
this.payableQueryParams.vendorName = this.queryParams.vendorName;
this.payableQueryParams.payableBillCode = this.queryParams.payableBillCode;
this.payableQueryParams.params = {};
if (null != this.payableDateRange && '' != this.payableDateRange) {
this.payableQueryParams.params["beginTime"] = this.payableDateRange[0];
this.payableQueryParams.params["endTime"] = this.payableDateRange[1];
}
this.paymentQueryParams.vendorName = this.queryParams.vendorName;
this.paymentQueryParams.paymentCode = this.queryParams.paymentCode;
this.paymentQueryParams.params = {};
if (null != this.paymentDateRange && '' != this.paymentDateRange) {
this.paymentQueryParams.params["beginTime"] = this.paymentDateRange[0];
this.paymentQueryParams.params["endTime"] = this.paymentDateRange[1];
}
},
getPayableList() {
this.loadingPayable = true;
listPayable(this.payableQueryParams).then(response => {
this.payableList = response.rows.map(item => ({
...item,
currentWriteOffAmount: 0, // Initialize
selectedPlans: [] // Initialize
}));
this.payableTotal = response.total;
this.loadingPayable = false;
});
},
getPaymentList() {
this.loadingPayment = true;
listPayment(this.paymentQueryParams).then(response => {
this.paymentList = response.rows.map(item => ({
...item,
currentWriteOffAmount: 0, // Initialize
// Mocking fields not yet in standard listPayment (or assuming defaults)
unWrittenAmount: item.paymentAmount - (item.writtenAmount || 0),
writtenAmount: item.writtenAmount || 0
}));
this.paymentTotal = response.total;
this.loadingPayment = false;
});
},
// Logic for Plan Selection
handleOpenPlanSelector(row) {
this.currentPayableRow = row;
this.planDialogTitle = `选择应付计划 - ${row.payableBillCode}`;
this.planDialogVisible = true;
},
handlePlanSelectionConfirm() {
if (this.$refs.planSelector && this.$refs.planSelector.selectedPlan) {
const selected = this.$refs.planSelector.selectedPlan;
this.currentPayableRow.selectedPlans = selected;
// Calculate sum
const sum = selected.reduce((acc, plan) => acc + (plan.planAmount || 0), 0);
this.currentPayableRow.currentWriteOffAmount = sum;
this.$modal.msgSuccess(`已选择 ${selected.length} 个计划,总金额 ${sum.toFixed(2)}`);
}
this.planDialogVisible = false;
},
// Tax Calculations
calculateTax(amount, taxRate) {
if (!amount) return '0.00';
if (!taxRate) return '0.00';
// Formula depends on if amount is tax-inclusive.
// Typically unpaidAmount is Tax Inclusive.
// Tax = Amount - Amount / (1 + Rate/100)
// = Amount * (1 - 1/(1+Rate/100))
const rate = Number(taxRate) / 100;
const tax = amount - (amount / (1 + rate));
return tax.toFixed(2);
},
calculateExcludingTax(amount, taxRate) {
if (!amount) return '0.00';
// Amount / (1 + Rate/100)
const rate = Number(taxRate || 0) / 100;
const excl = amount / (1 + rate);
return excl.toFixed(2);
}
}
};
</script>
<style scoped>
.table-summary {
background-color: #f8f8f9;
padding: 10px;
border-radius: 4px;
border: 1px solid #ebeef5;
}
</style>

View File

@ -0,0 +1,567 @@
<template>
<div class="app-container">
<!-- 顶部按钮工具栏 -->
<div style="margin-bottom: 20px;">
<el-button type="primary" icon="el-icon-search" size="small" @click="handleOpenPayableFilter">
</el-button>
<el-button type="primary" icon="el-icon-search" size="small" @click="handleOpenPaymentFilter">
</el-button>
<el-button type="success" icon="el-icon-check" size="small" @click="handleManualWriteOff"></el-button>
</div>
<!-- 应付单过滤弹窗 -->
<el-dialog title="应付单查询条件" :visible.sync="payableFilterVisible" width="500px" append-to-body>
<el-form :model="queryParams" ref="payableQueryForm" size="small" label-width="120px">
<el-form-item label="制造商名称" prop="vendorName">
<el-select v-model="queryParams.vendorName" placeholder="请选择制造商名称" filterable clearable
style="width: 100%">
<el-option
v-for="item in vendorList"
:key="item.vendorCode"
:label="item.vendorName"
:value="item.vendorName"
/>
</el-select>
</el-form-item>
<el-form-item label="采购应付单编号" prop="payableBillCode">
<el-input v-model="queryParams.payableBillCode" placeholder="请输入采购应付单编号" clearable
@keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="应付单生成时间">
<el-date-picker
v-model="payableDateRange"
style="width: 100%"
value-format="yyyy-MM-dd HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button icon="el-icon-refresh" size="small" @click="resetPayableQuery"> </el-button>
<el-button type="primary" icon="el-icon-search" size="small" @click="handleQuery"> </el-button>
</div>
</el-dialog>
<!-- 付款单过滤弹窗 -->
<el-dialog title="付款单查询条件" :visible.sync="paymentFilterVisible" width="500px" append-to-body>
<el-form :model="queryParams" ref="paymentQueryForm" size="small" label-width="120px">
<el-form-item label="制造商名称" prop="vendorName">
<el-select v-model="queryParams.vendorName" placeholder="请选择制造商名称" filterable clearable
style="width: 100%">
<el-option
v-for="item in vendorList"
:key="item.vendorCode"
:label="item.vendorName"
:value="item.vendorName"
/>
</el-select>
</el-form-item>
<el-form-item label="采购付款单编号" prop="paymentCode">
<el-input v-model="queryParams.paymentCode" placeholder="请输入采购付款单编号" clearable
@keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="付款单生成时间">
<el-date-picker
v-model="paymentDateRange"
style="width: 100%"
value-format="yyyy-MM-dd HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button icon="el-icon-refresh" size="small" @click="resetPaymentQuery"> </el-button>
<el-button type="primary" icon="el-icon-search" size="small" @click="handleQuery"> </el-button>
</div>
</el-dialog>
<div v-if="showTables">
<!-- 采购应付单表格 -->
<h3>采购应付单</h3>
<div class="table-summary" style="margin-bottom: 10px;">
<span style="font-weight: bold; margin-right: 20px;">应付单本次核销总额: <span
style="color: #409EFF">{{ totalPayableWriteOffAmount.toFixed(2) }}</span></span>
</div>
<el-table
v-loading="loadingPayable"
:data="payableList"
border
@selection-change="handlePayableSelectionChange"
ref="payableTable"
row-key="id"
>
<el-table-column type="selection" width="55" align="center"/>
<el-table-column label="本次核销金额(元)" align="center" width="150">
<template slot-scope="scope">
<el-input
v-model="scope.row.currentWriteOffAmount"
placeholder="点击选择计划"
readonly
@click.native="handleOpenPlanSelector(scope.row)"
style="cursor: pointer;"
>
<i slot="suffix" class="el-input__icon el-icon-search"></i>
</el-input>
</template>
</el-table-column>
<el-table-column label="未核销含税总价(元)" align="center" prop="unpaidPaymentAmount" width="150"/>
<el-table-column label="未核销未税总价(元)" align="center" prop="unpaidAmount" width="150">
<template slot-scope="scope">
{{ calculateExcludingTax(scope.row.unpaidPaymentAmount, scope.row.taxRate) }}
</template>
</el-table-column>
<el-table-column label="未核销税额(元)" align="center" width="150">
<template slot-scope="scope">
{{ calculateTax(scope.row.unpaidPaymentAmount, scope.row.taxRate) }}
</template>
</el-table-column>
<el-table-column label="核销中含税总价(元)" align="center" prop="paidAmount" width="150">
<template slot-scope="scope">
{{
$calc.sub($calc.sub(scope.row.totalPriceWithTax, scope.row.paidPaymentAmount), scope.row.unpaidPaymentAmount)
}}
</template>
</el-table-column>
<el-table-column label="已核销含税总价(元)" align="center" prop="paidPaymentAmount" width="150"/>
<el-table-column label="已核销未税总价(元)" align="center" width="150">
<template slot-scope="scope">
{{ calculateExcludingTax(scope.row.paidPaymentAmount, scope.row.taxRate) }}
</template>
</el-table-column>
<el-table-column label="已核销税额(元)" align="center" width="120">
<template slot-scope="scope">
{{ calculateTax(scope.row.paidPaymentAmount, scope.row.taxRate) }}
</template>
</el-table-column>
<el-table-column label="含税总价(元)" align="center" prop="totalPriceWithTax" width="120"/>
<el-table-column label="制造商名称" fixed="right" align="center" prop="vendorName" width="150"
show-overflow-tooltip/>
<el-table-column label="采购应付单编号" fixed="right" align="center" prop="payableBillCode" width="150"
show-overflow-tooltip/>
<el-table-column label="应付单生成时间" fixed="right" align="center" prop="createTime" width="160">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="payableTotal>0"
:total="payableTotal"
:pageSizes="[5,10,20,50]"
:page.sync="payableQueryParams.pageNum"
:limit.sync="payableQueryParams.pageSize"
@pagination="getPayableList"
/>
<!-- 采购付款单表格 -->
<h3 style="margin-top: 30px;">采购付款单</h3>
<div class="table-summary" style="margin-bottom: 10px;">
<span style="font-weight: bold; margin-right: 20px;">付款单本次核销总额: <span
:style="{color: isWriteOffAmountValid ? '#67C23A' : '#F56C6C'}">{{
totalPaymentWriteOffAmount.toFixed(2)
}}</span></span>
<span v-if="!isWriteOffAmountValid" style="color: #F56C6C; font-size: 12px;"><i class="el-icon-warning"></i> </span>
</div>
<el-table v-loading="loadingPayment" :data="paymentList" border highlight-current-row
@current-change="handlePaymentSelectionChange" row-key="id">
<el-table-column width="55" align="center">
<template slot-scope="scope">
<el-radio v-model="selectedPaymentId" :label="scope.row.paymentBillCode"><i></i></el-radio>
</template>
</el-table-column>
<el-table-column label="本次核销含税总价(元)" align="center" width="150">
<template slot-scope="scope">
<el-input-number
v-model="scope.row.currentWriteOffAmount"
:precision="2"
:step="100"
:min="0"
:max="scope.row.unWrittenAmount || scope.row.paymentAmount"
size="small"
style="width: 100%"
:disabled="selectedPaymentId !== scope.row.paymentBillCode"
/>
</template>
</el-table-column>
<el-table-column label="未核销含税总价(元)" align="center" width="150">
<template slot-scope="scope">
{{ scope.row.preResidueAmount || '0.00' }} <!-- Assuming paymentAmount is total initially -->
</template>
</el-table-column>
<el-table-column label="已核销含税总价(元)" align="center" prop="writeOffAmount" width="150"/>
<el-table-column label="已核销未税总价(元)" align="center" width="150" prop="writeOffAmountWithoutTax"/>
<el-table-column label="已核销税额(元)" align="center" width="150" prop="writeOffTaxAmount"/>
<el-table-column label="含税总价(元)" align="center" prop="totalPriceWithTax"/>
<el-table-column label="制造商名称" fixed="right" align="center" prop="vendorName" width="150"
show-overflow-tooltip/>
<el-table-column label="采购付款单号" fixed="right" align="center" prop="paymentBillCode" width="150"
show-overflow-tooltip/>
<el-table-column label="付款单生成时间" fixed="right" align="center" prop="createTime" width="160">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="paymentTotal>0"
:total="paymentTotal"
:page.sync="paymentQueryParams.pageNum"
:limit.sync="paymentQueryParams.pageSize"
@pagination="getPaymentList"
:pageSizes="[5,10,20,50]"
/>
</div>
<!-- 弹窗选择应付计划 -->
<el-dialog :title="planDialogTitle" :visible.sync="planDialogVisible" width="70%" append-to-body>
<payment-plan-selector
v-if="planDialogVisible"
ref="planSelector"
:payable-data="currentPayableRow"
:selected-plans="currentPayableRow ? currentPayableRow.selectedPlans : []"
:is-init-edit="false"
/>
<!-- Note: is-init-edit=false makes it read-only for editing plans generally, but we want to SELECT.
PaymentPlanSelector logic: 'selection-change' works.
If PaymentPlanSelector allows selection only in some mode, we need to check.
Looking at PaymentPlan.vue: <el-table ... @selection-change="selectPlan">
It seems selection is always enabled.
-->
<div slot="footer" class="dialog-footer">
<el-button @click="planDialogVisible = false"> </el-button>
<el-button type="primary" @click="handlePlanSelectionConfirm"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {listPayable} from "@/api/finance/payable";
import {listPaymentForWriteOff, manualWriteOff} from "@/api/finance/payment";
import {listAllVendors} from "@/api/inventory/info";
import PaymentPlanSelector from "../../payable/components/PaymentPlan.vue";
export default {
name: "ManualWriteOff",
components: {PaymentPlanSelector},
dicts: ['payment_status', 'payment_bill_type'],
data() {
return {
//
payableFilterVisible: false,
paymentFilterVisible: false,
//
loadingPayable: false,
loadingPayment: false,
//
showTables: false,
//
queryParams: {
vendorName: undefined,
payableBillCode: undefined,
paymentCode: undefined,
},
payableDateRange: [],
paymentDateRange: [],
vendorList: [], //
//
payableList: [],
payableTotal: 0,
payableQueryParams: {
pageNum: 1,
pageSize: 5,
vendorName: undefined,
payableBillCode: undefined,
unpaidPaymentAmount: -1,
params: {}
},
selectedPayables: [], //
//
paymentList: [],
paymentTotal: 0,
paymentQueryParams: {
pageNum: 1,
pageSize: 5,
vendorName: undefined,
paymentCode: undefined,
paymentBillType: 'PRE_PAYMENT', //
paymentStatus: '2',
params: {}
},
selectedPaymentId: null, // ID (使 BillCode)
selectedPaymentRow: null, //
//
planDialogVisible: false,
currentPayableRow: null,
planDialogTitle: "选择应付计划"
};
},
watch: {
totalPayableWriteOffAmount(newVal) {
this.updatePaymentWriteOffAmount();
}
},
computed: {
totalPayableWriteOffAmount() {
return this.selectedPayables.reduce((sum, row) => sum + (row.currentWriteOffAmount || 0), 0);
},
totalPaymentWriteOffAmount() {
if (!this.selectedPaymentRow) return 0;
return this.selectedPaymentRow.currentWriteOffAmount || 0;
},
isWriteOffAmountValid() {
// use a small epsilon for float comparison if needed, but direct comparison is usually okay for UI validation
return this.totalPaymentWriteOffAmount <= this.totalPayableWriteOffAmount + 0.01;
}
},
created() {
this.getVendorList();
this.payableFilterVisible = true; //
},
methods: {
getVendorList() {
listAllVendors().then(response => {
// { data: [...] } search_file controller AjaxResult .data .rows
// Ruoyi response.data
this.vendorList = response.data || [];
});
},
handleOpenPayableFilter() {
this.payableFilterVisible = true;
},
handleOpenPaymentFilter() {
this.paymentFilterVisible = true;
},
/** 搜索按钮操作 */
handleQuery() {
if (!this.queryParams.vendorName) {
this.$modal.msgError("请选择制造商名称");
return;
}
this.payableFilterVisible = false;
this.paymentFilterVisible = false;
this.showTables = true;
this.payableQueryParams.pageNum = 1;
this.paymentQueryParams.pageNum = 1;
this.syncParams();
this.getPayableList();
this.getPaymentList();
},
/** 重置按钮操作 */
resetPayableQuery() {
this.payableDateRange = [];
this.queryParams.vendorName = undefined;
this.queryParams.payableBillCode = undefined;
},
resetPaymentQuery() {
this.paymentDateRange = [];
this.queryParams.vendorName = undefined;
this.queryParams.paymentCode = undefined;
},
syncParams() {
this.payableQueryParams.vendorName = this.queryParams.vendorName;
this.payableQueryParams.payableBillCode = this.queryParams.payableBillCode;
this.payableQueryParams.params = {};
if (null != this.payableDateRange && '' != this.payableDateRange) {
this.payableQueryParams.params["beginTime"] = this.payableDateRange[0];
this.payableQueryParams.params["endTime"] = this.payableDateRange[1];
}
this.paymentQueryParams.vendorName = this.queryParams.vendorName;
this.paymentQueryParams.paymentCode = this.queryParams.paymentCode;
this.paymentQueryParams.paymentBillType = 'PRE_PAYMENT'; //
this.paymentQueryParams.params = {};
if (null != this.paymentDateRange && '' != this.paymentDateRange) {
this.paymentQueryParams.params["beginTime"] = this.paymentDateRange[0];
this.paymentQueryParams.params["endTime"] = this.paymentDateRange[1];
}
},
getPayableList() {
this.loadingPayable = true;
listPayable(this.payableQueryParams).then(response => {
this.payableList = response.rows.map(item => ({
...item,
currentWriteOffAmount: 0, // Initialize
selectedPlans: [] // Initialize
}));
this.payableTotal = response.total;
this.loadingPayable = false;
//
this.$refs.payableTable.clearSelection();
this.selectedPayables = [];
});
},
getPaymentList() {
this.loadingPayment = true;
listPaymentForWriteOff(this.paymentQueryParams).then(response => {
this.paymentList = response.rows.map(item => ({
...item,
currentWriteOffAmount: 0, // Initialize
// Mocking fields not yet in standard listPayment (or assuming defaults)
unWrittenAmount: item.paymentAmount - (item.writtenAmount || 0),
writtenAmount: item.writtenAmount || 0
}));
this.paymentTotal = response.total;
this.loadingPayment = false;
//
this.selectedPaymentId = null;
this.selectedPaymentRow = null;
});
},
handlePayableSelectionChange(selection) {
this.selectedPayables = selection;
},
handlePaymentSelectionChange(currentRow) {
if (currentRow) {
this.selectedPaymentId = currentRow.paymentBillCode;
this.selectedPaymentRow = currentRow;
//
this.updatePaymentWriteOffAmount();
} else {
this.selectedPaymentId = null;
this.selectedPaymentRow = null;
}
},
// Logic for Plan Selection
handleOpenPlanSelector(row) {
this.currentPayableRow = row;
this.planDialogTitle = `选择应付计划 - ${row.payableBillCode}`;
this.planDialogVisible = true;
},
handlePlanSelectionConfirm() {
if (this.$refs.planSelector && this.$refs.planSelector.selectedPlan) {
const selected = this.$refs.planSelector.selectedPlan;
this.currentPayableRow.selectedPlans = selected;
// Calculate sum
const sum = selected.reduce((acc, plan) => acc + (plan.planAmount || 0), 0);
this.currentPayableRow.currentWriteOffAmount = sum;
this.$modal.msgSuccess(`已选择 ${selected.length} 个计划,总金额 ${sum.toFixed(2)}`);
// 1.
if (selected.length > 0) {
this.$refs.payableTable.toggleRowSelection(this.currentPayableRow, true);
} else {
this.$refs.payableTable.toggleRowSelection(this.currentPayableRow, false);
}
}
this.planDialogVisible = false;
},
// Tax Calculations
calculateTax(amount, taxRate) {
let calculateExcludingTax = this.calculateExcludingTax(amount, taxRate);
return this.$calc.sub(amount, calculateExcludingTax)
},
calculateExcludingTax(amount, taxRate) {
if (!amount) return '0.00';
// Amount / (1 + Rate/100)
const rate = taxRate ?? 0.13;
return this.$calc.div(amount, this.$calc.add(1, rate))
},
//
updatePaymentWriteOffAmount() {
if (this.selectedPaymentRow) {
const payableSum = this.totalPayableWriteOffAmount;
const maxAmount = this.selectedPaymentRow.unWrittenAmount || this.selectedPaymentRow.preResidueAmount || 0; // Use preResidueAmount if unWrittenAmount is not reliable or prefered
if (payableSum > maxAmount) {
//
this.selectedPaymentRow.currentWriteOffAmount = maxAmount;
this.$modal.msgWarning(`应付单核销总额(${payableSum.toFixed(2)})超过付款单剩余额度(${maxAmount}),已自动调整为最大可核销额度。`);
} else {
this.selectedPaymentRow.currentWriteOffAmount = payableSum;
}
}
},
//
handleManualWriteOff() {
if (!this.selectedPaymentRow) {
this.$modal.msgError("请选择一个付款单");
return;
}
if (this.selectedPayables.length === 0) {
this.$modal.msgError("请至少选择一个应付单");
return;
}
//
// 使 epsilon
if (Math.abs(this.totalPaymentWriteOffAmount - this.totalPayableWriteOffAmount) > 0.01) {
this.$modal.msgError(`付款单核销金额(${this.totalPaymentWriteOffAmount.toFixed(2)})必须等于应付单核销总额(${this.totalPayableWriteOffAmount.toFixed(2)})`);
return;
}
const detailList = [];
this.selectedPayables.forEach(payable => {
if (payable.selectedPlans && payable.selectedPlans.length > 0) {
payable.selectedPlans.forEach(plan => {
const amount = plan.planAmount;
detailList.push({
paymentPlanId: plan.id,
payableBillId: payable.id,
paymentBillCode: this.selectedPaymentRow.paymentBillCode,
paymentAmount: amount,
paymentRate: plan.planRate,
paymentAmountWithoutTax: this.calculateExcludingTax(amount, payable.taxRate),
paymentAmountTax: this.calculateTax(amount, payable.taxRate)
});
});
}
});
if (detailList.length === 0) {
this.$modal.msgError("请为选中的应付单选择计划(点击放大镜图标)");
return;
}
let vendorCode = this.selectedPaymentRow.vendorCode;
// Fallback for vendorCode if not in row but in list
if (!vendorCode && this.selectedPaymentRow.vendorName) {
const vendor = this.vendorList.find(v => v.vendorName === this.selectedPaymentRow.vendorName);
if (vendor) vendorCode = vendor.vendorCode;
}
const data = {
paymentBillId: this.selectedPaymentRow.paymentBillId || this.selectedPaymentRow.id,
vendorCode: vendorCode,
detailList: detailList
};
manualWriteOff(data).then(response => {
this.$modal.msgSuccess("核销成功");
this.handleQuery();
});
}
}
};
</script>
<style scoped>
.table-summary {
background-color: #f8f8f9;
padding: 10px;
border-radius: 4px;
border: 1px solid #ebeef5;
}
</style>

View File

@ -1,29 +1,21 @@
package com.ruoyi.sip.controller; package com.ruoyi.sip.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
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.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.sip.domain.OmsPayableWriteOff; import com.ruoyi.sip.domain.OmsPayableWriteOff;
import com.ruoyi.sip.dto.WriteOffRequestDto;
import com.ruoyi.sip.dto.WriteOffQueryDto;
import com.ruoyi.sip.dto.WriteOffDetailResultDto; import com.ruoyi.sip.dto.WriteOffDetailResultDto;
import com.ruoyi.sip.dto.WriteOffRequestDto;
import com.ruoyi.sip.service.IOmsPayableWriteOffService; import com.ruoyi.sip.service.IOmsPayableWriteOffService;
import com.ruoyi.common.core.page.TableDataInfo; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/** /**
* Controller * Controller
@ -32,7 +24,7 @@ import com.ruoyi.common.core.page.TableDataInfo;
* @date 2025-12-16 * @date 2025-12-16
*/ */
@RestController @RestController
@RequestMapping("/sip/writeOff") @RequestMapping("/finance/writeoff")
public class OmsPayableWriteOffController extends BaseController public class OmsPayableWriteOffController extends BaseController
{ {
@Autowired @Autowired
@ -43,7 +35,7 @@ public class OmsPayableWriteOffController extends BaseController
*/ */
@RequiresPermissions("sip:writeOff:list") @RequiresPermissions("sip:writeOff:list")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(WriteOffQueryDto writeOffQueryDto) public TableDataInfo list(OmsPayableWriteOff writeOffQueryDto)
{ {
startPage(); startPage();
List<OmsPayableWriteOff> list = omsPayableWriteOffService.selectOmsPayableWriteOffList(writeOffQueryDto); List<OmsPayableWriteOff> list = omsPayableWriteOffService.selectOmsPayableWriteOffList(writeOffQueryDto);
@ -56,7 +48,7 @@ public class OmsPayableWriteOffController extends BaseController
@RequiresPermissions("sip:writeOff:export") @RequiresPermissions("sip:writeOff:export")
@Log(title = "采购应付核销单", businessType = BusinessType.EXPORT) @Log(title = "采购应付核销单", businessType = BusinessType.EXPORT)
@PostMapping("/export") @PostMapping("/export")
public void export(HttpServletResponse response, WriteOffQueryDto writeOffQueryDto) public void export(HttpServletResponse response, OmsPayableWriteOff writeOffQueryDto)
{ {
List<OmsPayableWriteOff> list = omsPayableWriteOffService.selectOmsPayableWriteOffList(writeOffQueryDto); List<OmsPayableWriteOff> list = omsPayableWriteOffService.selectOmsPayableWriteOffList(writeOffQueryDto);
ExcelUtil<OmsPayableWriteOff> util = new ExcelUtil<OmsPayableWriteOff>(OmsPayableWriteOff.class); ExcelUtil<OmsPayableWriteOff> util = new ExcelUtil<OmsPayableWriteOff>(OmsPayableWriteOff.class);

View File

@ -68,6 +68,14 @@ public class OmsPaymentBillController extends BaseController
, OmsPaymentBill::getPaymentBillCode, (a, b) -> a.setApproveNode(b.get(a.getPaymentBillCode()))); , OmsPaymentBill::getPaymentBillCode, (a, b) -> a.setApproveNode(b.get(a.getPaymentBillCode())));
return getDataTable(list); return getDataTable(list);
} }
@PostMapping("/write-off/list")
@ResponseBody
public TableDataInfo listWriteOff(OmsPaymentBill omsPaymentBill)
{
startPage();
List<OmsPaymentBill> list = omsPaymentBillService.listWriteOff(omsPaymentBill);
return getDataTable(list);
}
@RequiresPermissions("finance:payment:approve") @RequiresPermissions("finance:payment:approve")

View File

@ -20,9 +20,12 @@ public class OmsPayablePaymentDetail extends BaseEntity {
private Date paymentTime; private Date paymentTime;
private BigDecimal paymentAmount; private BigDecimal paymentAmount;
private BigDecimal paymentAmountWithoutTax;
private BigDecimal paymentAmountTax;
private BigDecimal paymentRate; private BigDecimal paymentRate;
private String paymentBillCode; private String paymentBillCode;
private Long paymentBillId; private Long paymentBillId;
private Long writeOffId;
private Date actualPaymentTime; private Date actualPaymentTime;
private String paymentStatus; private String paymentStatus;
@ -36,6 +39,7 @@ public class OmsPayablePaymentDetail extends BaseEntity {
/** 已确认 */ /** 已确认 */
PREPAY_WRITE_OFF("2", "预付核销"), PREPAY_WRITE_OFF("2", "预付核销"),
REFUND("3", "退款"), REFUND("3", "退款"),
REFUND_WRITE_OFF("4", "反核销"),
; ;

View File

@ -2,11 +2,14 @@ package com.ruoyi.sip.domain;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter;
/** /**
* oms_payable_write_off * oms_payable_write_off
@ -34,10 +37,12 @@ public class OmsPayableWriteOff extends BaseEntity
/** 付款单编号 */ /** 付款单编号 */
@Excel(name = "付款单编号") @Excel(name = "付款单编号")
private String paymentBillCode; private String paymentBillCode;
private List<String> paymentBillCodeList;
/** 供应商编码 */ /** 供应商编码 */
@Excel(name = "供应商编码") @Excel(name = "供应商编码")
private String vendorCode; private String vendorCode;
private String vendorName;
/** 本次核销总金额 */ /** 本次核销总金额 */
@Excel(name = "本次核销总金额") @Excel(name = "本次核销总金额")
@ -62,6 +67,7 @@ public class OmsPayableWriteOff extends BaseEntity
/** 创建人 */ /** 创建人 */
private String createBy; private String createBy;
private String createByName;
/** 创建时间 */ /** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ -73,4 +79,20 @@ public class OmsPayableWriteOff extends BaseEntity
/** 更新时间 */ /** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime; private Date updateTime;
@Getter
public enum WriteOffTypeEnum {
AUTO("AUTO", "自动核销"),
USER("USER", "手动核销"),
;
private final String code;
private final String desc;
WriteOffTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
}
} }

View File

@ -135,6 +135,10 @@ public class OmsPaymentBill extends BaseEntity
private String taskId; private String taskId;
private BigDecimal writeOffAmount;
private BigDecimal writeOffAmountWithoutTax;
private BigDecimal writeOffTaxAmount;
@Getter @Getter
public enum PaymentBillTypeEnum { public enum PaymentBillTypeEnum {

View File

@ -47,6 +47,7 @@ public class WriteOffItemDto
* *
*/ */
private BigDecimal writeOffTaxAmount; private BigDecimal writeOffTaxAmount;
private BigDecimal paymentRate;
/** /**
* *

View File

@ -1,38 +0,0 @@
package com.ruoyi.sip.dto;
import com.ruoyi.common.core.domain.BaseEntity;
import java.util.Date;
/**
* DTO
*
* @author zghz
* @date 2025-12-16
*/
public class WriteOffQueryDto extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 核销单号 */
private String writeOffCode;
/** 供货商代码 */
private String vendorCode;
// Getters and Setters
public String getWriteOffCode() {
return writeOffCode;
}
public void setWriteOffCode(String writeOffCode) {
this.writeOffCode = writeOffCode;
}
public String getVendorCode() {
return vendorCode;
}
public void setVendorCode(String vendorCode) {
this.vendorCode = vendorCode;
}
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.sip.dto; package com.ruoyi.sip.dto;
import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;
@ -24,7 +25,7 @@ public class WriteOffRequestDto
/** /**
* *
*/ */
private List<WriteOffItemDto> writeOffItems; private List<OmsPayablePaymentDetail> detailList;
/** /**
* *

View File

@ -1,85 +0,0 @@
package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.OmsPayableWriteOffDetail;
/**
* Mapper
*
* @author zghz
* @date 2025-12-16
*/
public interface OmsPayableWriteOffDetailMapper
{
/**
*
*
* @param id ID
* @return
*/
public OmsPayableWriteOffDetail selectOmsPayableWriteOffDetailById(Long id);
/**
*
*
* @param omsPayableWriteOffDetail
* @return
*/
public List<OmsPayableWriteOffDetail> selectOmsPayableWriteOffDetailList(OmsPayableWriteOffDetail omsPayableWriteOffDetail);
/**
*
*
* @param omsPayableWriteOffDetail
* @return
*/
public int insertOmsPayableWriteOffDetail(OmsPayableWriteOffDetail omsPayableWriteOffDetail);
/**
*
*
* @param omsPayableWriteOffDetail
* @return
*/
public int updateOmsPayableWriteOffDetail(OmsPayableWriteOffDetail omsPayableWriteOffDetail);
/**
*
*
* @param id ID
* @return
*/
public int deleteOmsPayableWriteOffDetailById(Long id);
/**
*
*
* @param ids ID
* @return
*/
public int deleteOmsPayableWriteOffDetailByIds(Long[] ids);
/**
* ID
*
* @param writeOffId ID
* @return
*/
public int deleteOmsPayableWriteOffDetailByWriteOffId(Long writeOffId);
/**
*
*
* @param writeOffIds ID
* @return
*/
public int deleteOmsPayableWriteOffDetailByWriteOffIds(Long[] writeOffIds);
/**
* ID
*
* @param writeOffId ID
* @return
*/
public List<OmsPayableWriteOffDetail> selectOmsPayableWriteOffDetailByWriteOffId(Long writeOffId);
}

View File

@ -1,6 +1,7 @@
package com.ruoyi.sip.service; package com.ruoyi.sip.service;
import com.ruoyi.sip.domain.OmsPayablePaymentDetail; import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
import com.ruoyi.sip.domain.OmsPayableWriteOffDetail;
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO; import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
import java.util.List; import java.util.List;
@ -17,4 +18,8 @@ public interface IOmsPayablePaymentDetailService {
List<OmsPayablePaymentDetail> selectByPaymentPlanIds(List<Long> paymentPlanIds); List<OmsPayablePaymentDetail> selectByPaymentPlanIds(List<Long> paymentPlanIds);
List<OmsPayablePaymentDetail> listBypaymentCode(String paymentBillCode); List<OmsPayablePaymentDetail> listBypaymentCode(String paymentBillCode);
void insertBatch(List<OmsPayablePaymentDetail> detailList);
// List<OmsPayableWriteOffDetail> listWriteOffByPaymentCode(List<String> );
} }

View File

@ -1,10 +1,10 @@
package com.ruoyi.sip.service; package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsPayableWriteOff; import com.ruoyi.sip.domain.OmsPayableWriteOff;
import com.ruoyi.sip.dto.WriteOffRequestDto;
import com.ruoyi.sip.dto.WriteOffQueryDto;
import com.ruoyi.sip.dto.WriteOffDetailResultDto; import com.ruoyi.sip.dto.WriteOffDetailResultDto;
import com.ruoyi.sip.dto.WriteOffRequestDto;
import java.util.List;
/** /**
* Service * Service
@ -28,7 +28,7 @@ public interface IOmsPayableWriteOffService
* @param writeOffQueryDto * @param writeOffQueryDto
* @return * @return
*/ */
public List<OmsPayableWriteOff> selectOmsPayableWriteOffList(WriteOffQueryDto writeOffQueryDto); public List<OmsPayableWriteOff> selectOmsPayableWriteOffList(OmsPayableWriteOff writeOffQueryDto);
/** /**
* *
@ -69,4 +69,6 @@ public interface IOmsPayableWriteOffService
* @return * @return
*/ */
public List<WriteOffDetailResultDto> selectWriteOffDetailsByWriteOffId(Long writeOffId); public List<WriteOffDetailResultDto> selectWriteOffDetailsByWriteOffId(Long writeOffId);
List<OmsPayableWriteOff> listByPaymentBillCodeList(List<String> collect);
} }

View File

@ -103,4 +103,6 @@ public interface IOmsPaymentBillService
AjaxResult revoke(OmsPaymentBill paymentBill); AjaxResult revoke(OmsPaymentBill paymentBill);
AjaxResult applyRefundApprove(OmsPaymentBill paymentBill); AjaxResult applyRefundApprove(OmsPaymentBill paymentBill);
List<OmsPaymentBill> listWriteOff(OmsPaymentBill omsPaymentBill);
} }

View File

@ -112,4 +112,9 @@ public class OmsPayablePaymentDetailServiceImpl implements IOmsPayablePaymentDet
omsPayablePaymentDetail.setPaymentBillCode(paymentBillCode); omsPayablePaymentDetail.setPaymentBillCode(paymentBillCode);
return omsPayablePaymentDetailMapper.list(omsPayablePaymentDetail); return omsPayablePaymentDetailMapper.list(omsPayablePaymentDetail);
} }
@Override
public void insertBatch(List<OmsPayablePaymentDetail> detailList) {
omsPayablePaymentDetailMapper.insertBatch(detailList);
}
} }

View File

@ -1,27 +1,29 @@
package com.ruoyi.sip.service; package com.ruoyi.sip.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
import com.ruoyi.sip.domain.OmsPayableWriteOff;
import com.ruoyi.sip.domain.OmsPayableWriteOffDetail;
import com.ruoyi.sip.domain.OmsPaymentBill;
import com.ruoyi.sip.dto.WriteOffDetailResultDto;
import com.ruoyi.sip.dto.WriteOffRequestDto;
import com.ruoyi.sip.mapper.OmsPayableWriteOffMapper;
import com.ruoyi.sip.mapper.OmsPaymentBillMapper;
import com.ruoyi.sip.service.IOmsPayableBillService;
import com.ruoyi.sip.service.IOmsPayablePaymentDetailService;
import com.ruoyi.sip.service.IOmsPayableWriteOffService;
import com.ruoyi.sip.utils.WriteOffCodeGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.sip.domain.OmsPayableWriteOff;
import com.ruoyi.sip.domain.OmsPayableWriteOffDetail;
import com.ruoyi.sip.domain.OmsPayableBill;
import com.ruoyi.sip.domain.OmsPaymentBill;
import com.ruoyi.sip.domain.OmsPayablePaymentPlan;
import com.ruoyi.sip.mapper.OmsPayableWriteOffMapper;
import com.ruoyi.sip.mapper.OmsPayableWriteOffDetailMapper;
import com.ruoyi.sip.mapper.OmsPayableBillMapper;
import com.ruoyi.sip.mapper.OmsPaymentBillMapper;
import com.ruoyi.sip.mapper.OmsPayablePaymentPlanMapper;
import com.ruoyi.sip.dto.WriteOffRequestDto;
import com.ruoyi.sip.dto.WriteOffItemDto;
import com.ruoyi.sip.dto.WriteOffQueryDto;
import com.ruoyi.sip.dto.WriteOffDetailResultDto;
import com.ruoyi.sip.utils.WriteOffCodeGenerator;
/** /**
* Service * Service
@ -35,14 +37,14 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
@Autowired @Autowired
private OmsPayableWriteOffMapper omsPayableWriteOffMapper; private OmsPayableWriteOffMapper omsPayableWriteOffMapper;
@Autowired
private OmsPayableWriteOffDetailMapper omsPayableWriteOffDetailMapper;
@Autowired
private OmsPayableBillMapper omsPayableBillMapper;
@Autowired @Autowired
private OmsPaymentBillMapper omsPaymentBillMapper; private OmsPaymentBillMapper omsPaymentBillMapper;
@Autowired
private IOmsPayablePaymentDetailService omsPayablePaymentDetailService;
@Autowired
private IOmsPayableBillService payableBillService;
/** /**
@ -64,12 +66,8 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
* @return * @return
*/ */
@Override @Override
public List<OmsPayableWriteOff> selectOmsPayableWriteOffList(WriteOffQueryDto writeOffQueryDto) public List<OmsPayableWriteOff> selectOmsPayableWriteOffList(OmsPayableWriteOff omsPayableWriteOff)
{ {
OmsPayableWriteOff omsPayableWriteOff = new OmsPayableWriteOff();
omsPayableWriteOff.setWriteOffCode(writeOffQueryDto.getWriteOffCode());
omsPayableWriteOff.setVendorCode(writeOffQueryDto.getVendorCode());
return omsPayableWriteOffMapper.selectOmsPayableWriteOffList(omsPayableWriteOff); return omsPayableWriteOffMapper.selectOmsPayableWriteOffList(omsPayableWriteOff);
} }
@ -83,17 +81,20 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
@Transactional @Transactional
public Long insertOmsPayableWriteOff(WriteOffRequestDto writeOffRequestDto) public Long insertOmsPayableWriteOff(WriteOffRequestDto writeOffRequestDto)
{ {
if (CollUtil.isEmpty(writeOffRequestDto.getDetailList())){
throw new ServiceException("请选择核销明细");
}
// 获取付款单信息 // 获取付款单信息
OmsPaymentBill paymentBill = omsPaymentBillMapper.selectOmsPaymentBillById(writeOffRequestDto.getPaymentBillId()); OmsPaymentBill paymentBill = omsPaymentBillMapper.selectOmsPaymentBillById(writeOffRequestDto.getPaymentBillId());
if (paymentBill == null) { if (paymentBill == null) {
throw new RuntimeException("付款单不存在"); throw new ServiceException("付款单不存在");
} }
// 创建核销主记录 // 创建核销主记录
OmsPayableWriteOff writeOff = new OmsPayableWriteOff(); OmsPayableWriteOff writeOff = new OmsPayableWriteOff();
writeOff.setWriteOffCode(WriteOffCodeGenerator.generateWriteOffCode()); writeOff.setWriteOffCode(WriteOffCodeGenerator.generateWriteOffCode());
// 默认为用户手动核销 // 默认为用户手动核销
writeOff.setWriteOffType("USER"); writeOff.setWriteOffType(OmsPayableWriteOff.WriteOffTypeEnum.USER.getCode());
writeOff.setPaymentBillCode(paymentBill.getPaymentBillCode()); writeOff.setPaymentBillCode(paymentBill.getPaymentBillCode());
writeOff.setVendorCode(writeOffRequestDto.getVendorCode()); writeOff.setVendorCode(writeOffRequestDto.getVendorCode());
writeOff.setWriteOffTime(new Date()); writeOff.setWriteOffTime(new Date());
@ -104,51 +105,40 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
BigDecimal totalAmountWithoutTax = BigDecimal.ZERO; BigDecimal totalAmountWithoutTax = BigDecimal.ZERO;
BigDecimal totalTaxAmount = BigDecimal.ZERO; BigDecimal totalTaxAmount = BigDecimal.ZERO;
for (WriteOffItemDto item : writeOffRequestDto.getWriteOffItems()) { for (OmsPayablePaymentDetail item : writeOffRequestDto.getDetailList()) {
totalAmount = totalAmount.add(item.getWriteOffAmount()); totalAmount = totalAmount.add(item.getPaymentAmount());
totalAmountWithoutTax = totalAmountWithoutTax.add(item.getWriteOffAmountWithoutTax()); totalAmountWithoutTax = totalAmountWithoutTax.add(item.getPaymentAmountWithoutTax());
totalTaxAmount = totalTaxAmount.add(item.getWriteOffTaxAmount()); totalTaxAmount = totalTaxAmount.add(item.getPaymentAmountTax());
} }
writeOff.setWriteOffAmount(totalAmount); writeOff.setWriteOffAmount(totalAmount);
writeOff.setWriteOffAmountWithoutTax(totalAmountWithoutTax); writeOff.setWriteOffAmountWithoutTax(totalAmountWithoutTax);
writeOff.setWriteOffTaxAmount(totalTaxAmount); writeOff.setWriteOffTaxAmount(totalTaxAmount);
//预付额度减少
OmsPaymentBill updateBill = new OmsPaymentBill();
BigDecimal decimal = paymentBill.getPreResidueAmount().subtract(totalAmount);
if (decimal.compareTo(BigDecimal.ZERO) < 0) {
throw new RuntimeException("核销金额不能大于预付剩余额度");
}
updateBill.setPreResidueAmount(decimal);
updateBill.setId(paymentBill.getId());
omsPaymentBillMapper.updateOmsPaymentBill(updateBill);
// 设置创建时间 // 设置创建时间
writeOff.setCreateTime(new Date()); writeOff.setCreateTime(new Date());
writeOff.setCreateBy(ShiroUtils.getUserId().toString());
writeOff.setUpdateTime(new Date()); writeOff.setUpdateTime(new Date());
// 保存核销主记录 // 保存核销主记录
omsPayableWriteOffMapper.insertOmsPayableWriteOff(writeOff); omsPayableWriteOffMapper.insertOmsPayableWriteOff(writeOff);
// 保存核销明细 // 保存核销明细
for (WriteOffItemDto item : writeOffRequestDto.getWriteOffItems()) for (OmsPayablePaymentDetail omsPayablePaymentDetail : writeOffRequestDto.getDetailList()) {
{ omsPayablePaymentDetail.setPayableDetailType(OmsPayablePaymentDetail.PayableDetailTypeEnum.PREPAY_WRITE_OFF.getCode());
OmsPayableWriteOffDetail detail = new OmsPayableWriteOffDetail(); omsPayablePaymentDetail.setPaymentTime(DateUtils.getNowDate());
detail.setWriteOffId(writeOff.getId()); omsPayablePaymentDetail.setCreateBy(ShiroUtils.getUserId().toString());
detail.setPayableBillId(item.getPayableBillId()); omsPayablePaymentDetail.setWriteOffId(writeOff.getId());
detail.setPaymentPlanId(item.getPaymentPlanId());
detail.setPaymentBillId(item.getPaymentBillId());
detail.setWriteOffAmount(item.getWriteOffAmount());
detail.setWriteOffAmountWithoutTax(item.getWriteOffAmountWithoutTax());
detail.setWriteOffTaxAmount(item.getWriteOffTaxAmount());
detail.setRemark(item.getRemark());
detail.setCreateTime(new Date());
detail.setUpdateTime(new Date());
// 获取应付单编号
OmsPayableBill payableBill = omsPayableBillMapper.selectOmsPayableBillById(item.getPayableBillId());
if (payableBill != null) {
detail.setPayableBillCode(payableBill.getPayableBillCode());
} }
omsPayablePaymentDetailService.insertBatch( writeOffRequestDto.getDetailList());
// 设置付款单编号 payableBillService.updatePaymentAmount(writeOffRequestDto.getDetailList().stream().map(OmsPayablePaymentDetail::getPayableBillId).collect(Collectors.toList()));
detail.setPaymentBillCode(paymentBill.getPaymentBillCode());
// 保存核销明细记录
omsPayableWriteOffDetailMapper.insertOmsPayableWriteOffDetail(detail);
}
return writeOff.getId(); return writeOff.getId();
} }
@ -174,8 +164,11 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
@Transactional @Transactional
public int deleteOmsPayableWriteOffByIds(Long[] ids) public int deleteOmsPayableWriteOffByIds(Long[] ids)
{ {
//反核销逻辑 todo
// 先删除明细记录 // 先删除明细记录
omsPayableWriteOffDetailMapper.deleteOmsPayableWriteOffDetailByWriteOffIds(ids); // omsPayablePaymentDetailService.deleteOmsPayableWriteOffDetailByWriteOffIds(ids);
// 再删除主记录 // 再删除主记录
return omsPayableWriteOffMapper.deleteOmsPayableWriteOffByIds(ids); return omsPayableWriteOffMapper.deleteOmsPayableWriteOffByIds(ids);
} }
@ -190,10 +183,8 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
@Transactional @Transactional
public int deleteOmsPayableWriteOffById(Long id) public int deleteOmsPayableWriteOffById(Long id)
{ {
// 先删除明细记录
omsPayableWriteOffDetailMapper.deleteOmsPayableWriteOffDetailByWriteOffId(id);
// 再删除主记录 // 再删除主记录
return omsPayableWriteOffMapper.deleteOmsPayableWriteOffById(id); return deleteOmsPayableWriteOffByIds(new Long[]{id});
} }
/** /**
@ -205,8 +196,16 @@ public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
@Override @Override
public List<WriteOffDetailResultDto> selectWriteOffDetailsByWriteOffId(Long writeOffId) public List<WriteOffDetailResultDto> selectWriteOffDetailsByWriteOffId(Long writeOffId)
{ {
List<OmsPayableWriteOffDetail> details = omsPayableWriteOffDetailMapper.selectOmsPayableWriteOffDetailByWriteOffId(writeOffId); // List<OmsPayableWriteOffDetail> details = omsPayableWriteOffDetailMapper.selectOmsPayableWriteOffDetailByWriteOffId(writeOffId);
return details.stream().map(this::convertToWriteOffDetailResultDto).collect(Collectors.toList()); // return details.stream().map(this::convertToWriteOffDetailResultDto).collect(Collectors.toList());
return null;
}
@Override
public List<OmsPayableWriteOff> listByPaymentBillCodeList(List<String> collect) {
OmsPayableWriteOff omsPayableWriteOff = new OmsPayableWriteOff();
omsPayableWriteOff.setPaymentBillCodeList(collect);
return omsPayableWriteOffMapper.selectOmsPayableWriteOffList(omsPayableWriteOff);
} }
/** /**

View File

@ -1,5 +1,6 @@
package com.ruoyi.sip.service.impl; package com.ruoyi.sip.service.impl;
import java.math.BigDecimal;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -63,6 +64,8 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
private ProcessConfig processConfig; private ProcessConfig processConfig;
@Autowired @Autowired
protected ManagementService managementService; protected ManagementService managementService;
@Autowired
private IOmsPayableWriteOffService writeOffService;
/** /**
* *
* *
@ -462,4 +465,34 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
return AjaxResult.success("申请退款成功"); return AjaxResult.success("申请退款成功");
} }
@Override
public List<OmsPaymentBill> listWriteOff(OmsPaymentBill omsPaymentBill) {
omsPaymentBill.setPreResidueAmount(new BigDecimal("-1"));
List<OmsPaymentBill> omsPaymentBills = omsPaymentBillMapper.selectOmsPaymentBillList(omsPaymentBill);
if (CollUtil.isEmpty(omsPaymentBills)) {
return omsPaymentBills;
}
//实时计算已核销金额 查询核销数据
List<OmsPayableWriteOff> omsPayableWriteOffs = writeOffService.listByPaymentBillCodeList(omsPaymentBills.stream().map(OmsPaymentBill::getPaymentBillCode).collect(Collectors.toList()));
Map<String, List<OmsPayableWriteOff>> writeOffListMap = omsPayableWriteOffs.stream().collect(Collectors.groupingBy(OmsPayableWriteOff::getPaymentBillCode));
for (OmsPaymentBill paymentBill : omsPaymentBills) {
List<OmsPayableWriteOff> writeOffList = writeOffListMap.get(paymentBill.getPaymentBillCode());
BigDecimal writeOffAmount = BigDecimal.ZERO;
BigDecimal writeOffAmountWithoutTax = BigDecimal.ZERO;
BigDecimal writeOffTaxAmount = BigDecimal.ZERO;
if (CollUtil.isNotEmpty(writeOffList)) {
for (OmsPayableWriteOff omsPayableWriteOff : writeOffList) {
writeOffAmount = writeOffAmount.add(omsPayableWriteOff.getWriteOffAmount());
writeOffAmountWithoutTax = writeOffAmountWithoutTax.add(omsPayableWriteOff.getWriteOffAmountWithoutTax());
writeOffTaxAmount = writeOffTaxAmount.add(omsPayableWriteOff.getWriteOffTaxAmount());
}
}
paymentBill.setWriteOffAmount(writeOffAmount);
paymentBill.setWriteOffAmountWithoutTax(writeOffAmountWithoutTax);
paymentBill.setWriteOffTaxAmount(writeOffTaxAmount);
}
return omsPaymentBills;
}
} }

View File

@ -1,128 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.sip.mapper.OmsPayableWriteOffDetailMapper">
<resultMap type="com.ruoyi.sip.domain.OmsPayableWriteOffDetail" id="OmsPayableWriteOffDetailResult">
<result property="id" column="id" />
<result property="writeOffId" column="write_off_id" />
<result property="payableBillId" column="payable_bill_id" />
<result property="payableBillCode" column="payable_bill_code" />
<result property="paymentPlanId" column="payment_plan_id" />
<result property="paymentBillId" column="payment_bill_id" />
<result property="paymentBillCode" column="payment_bill_code" />
<result property="writeOffAmount" column="write_off_amount" />
<result property="writeOffAmountWithoutTax" column="write_off_amount_without_tax" />
<result property="writeOffTaxAmount" column="write_off_tax_amount" />
<result property="remark" column="remark" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectOmsPayableWriteOffDetailVo">
select id, write_off_id, payable_bill_id, payable_bill_code, payment_plan_id, payment_bill_id, payment_bill_code,
write_off_amount, write_off_amount_without_tax, write_off_tax_amount,
remark, create_by, create_time, update_by, update_time
from oms_payable_write_off_detail
</sql>
<select id="selectOmsPayableWriteOffDetailById" parameterType="Long" resultMap="OmsPayableWriteOffDetailResult">
<include refid="selectOmsPayableWriteOffDetailVo"/>
where id = #{id}
</select>
<select id="selectOmsPayableWriteOffDetailList" parameterType="com.ruoyi.sip.domain.OmsPayableWriteOffDetail" resultMap="OmsPayableWriteOffDetailResult">
<include refid="selectOmsPayableWriteOffDetailVo"/>
<where>
<if test="writeOffId != null"> and write_off_id = #{writeOffId}</if>
<if test="payableBillId != null"> and payable_bill_id = #{payableBillId}</if>
<if test="paymentPlanId != null"> and payment_plan_id = #{paymentPlanId}</if>
<if test="paymentBillId != null"> and payment_bill_id = #{paymentBillId}</if>
</where>
</select>
<select id="selectOmsPayableWriteOffDetailByWriteOffId" parameterType="Long" resultMap="OmsPayableWriteOffDetailResult">
<include refid="selectOmsPayableWriteOffDetailVo"/>
where write_off_id = #{writeOffId}
</select>
<insert id="insertOmsPayableWriteOffDetail" parameterType="com.ruoyi.sip.domain.OmsPayableWriteOffDetail" useGeneratedKeys="true" keyProperty="id">
insert into oms_payable_write_off_detail
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="writeOffId != null">write_off_id,</if>
<if test="payableBillId != null">payable_bill_id,</if>
<if test="payableBillCode != null and payableBillCode != ''">payable_bill_code,</if>
<if test="paymentPlanId != null">payment_plan_id,</if>
<if test="paymentBillId != null">payment_bill_id,</if>
<if test="paymentBillCode != null and paymentBillCode != ''">payment_bill_code,</if>
<if test="writeOffAmount != null">write_off_amount,</if>
<if test="writeOffAmountWithoutTax != null">write_off_amount_without_tax,</if>
<if test="writeOffTaxAmount != null">write_off_tax_amount,</if>
<if test="remark != null">remark,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="writeOffId != null">#{writeOffId},</if>
<if test="payableBillId != null">#{payableBillId},</if>
<if test="payableBillCode != null and payableBillCode != ''">#{payableBillCode},</if>
<if test="paymentPlanId != null">#{paymentPlanId},</if>
<if test="paymentBillId != null">#{paymentBillId},</if>
<if test="paymentBillCode != null and paymentBillCode != ''">#{paymentBillCode},</if>
<if test="writeOffAmount != null">#{writeOffAmount},</if>
<if test="writeOffAmountWithoutTax != null">#{writeOffAmountWithoutTax},</if>
<if test="writeOffTaxAmount != null">#{writeOffTaxAmount},</if>
<if test="remark != null">#{remark},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateOmsPayableWriteOffDetail" parameterType="com.ruoyi.sip.domain.OmsPayableWriteOffDetail">
update oms_payable_write_off_detail
<trim prefix="SET" suffixOverrides=",">
<if test="writeOffId != null">write_off_id = #{writeOffId},</if>
<if test="payableBillId != null">payable_bill_id = #{payableBillId},</if>
<if test="payableBillCode != null and payableBillCode != ''">payable_bill_code = #{payableBillCode},</if>
<if test="paymentPlanId != null">payment_plan_id = #{paymentPlanId},</if>
<if test="paymentBillId != null">payment_bill_id = #{paymentBillId},</if>
<if test="paymentBillCode != null and paymentBillCode != ''">payment_bill_code = #{paymentBillCode},</if>
<if test="writeOffAmount != null">write_off_amount = #{writeOffAmount},</if>
<if test="writeOffAmountWithoutTax != null">write_off_amount_without_tax = #{writeOffAmountWithoutTax},</if>
<if test="writeOffTaxAmount != null">write_off_tax_amount = #{writeOffTaxAmount},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteOmsPayableWriteOffDetailById" parameterType="Long">
delete from oms_payable_write_off_detail where id = #{id}
</delete>
<delete id="deleteOmsPayableWriteOffDetailByWriteOffId" parameterType="Long">
delete from oms_payable_write_off_detail where write_off_id = #{writeOffId}
</delete>
<delete id="deleteOmsPayableWriteOffDetailByWriteOffIds" parameterType="String">
delete from oms_payable_write_off_detail where write_off_id in
<foreach item="writeOffId" collection="array" open="(" separator="," close=")">
#{writeOffId}
</foreach>
</delete>
<delete id="deleteOmsPayableWriteOffDetailByIds" parameterType="String">
delete from oms_payable_write_off_detail where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -22,10 +22,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap> </resultMap>
<sql id="selectOmsPayableWriteOffVo"> <sql id="selectOmsPayableWriteOffVo">
select id, write_off_code, write_off_type, payment_bill_code, vendor_code, select t1.id, t1.write_off_code, t1.write_off_type, t1.payment_bill_code, t1.vendor_code,
write_off_amount, write_off_amount_without_tax, write_off_tax_amount, write_off_time, t1.write_off_amount, t1.write_off_amount_without_tax, t1.write_off_tax_amount, t1.write_off_time,
remark, create_by, create_time, update_by, update_time t1.remark, t1.create_by, t1.create_time, t1.update_by, t1.update_time,
from oms_payable_write_off t2.vendor_name,t3.user_name as create_by_name
from oms_payable_write_off t1
left join oms_vendor_info t2 on t1.vendor_code=t2.vendor_code
left join sys_user t3 on t1.create_by=t3.user_id
</sql> </sql>
<select id="selectOmsPayableWriteOffById" parameterType="Long" resultMap="OmsPayableWriteOffResult"> <select id="selectOmsPayableWriteOffById" parameterType="Long" resultMap="OmsPayableWriteOffResult">
@ -39,6 +42,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="writeOffCode != null and writeOffCode != ''"> and write_off_code = #{writeOffCode}</if> <if test="writeOffCode != null and writeOffCode != ''"> and write_off_code = #{writeOffCode}</if>
<if test="writeOffType != null and writeOffType != ''"> and write_off_type = #{writeOffType}</if> <if test="writeOffType != null and writeOffType != ''"> and write_off_type = #{writeOffType}</if>
<if test="paymentBillCode != null and paymentBillCode != ''"> and payment_bill_code = #{paymentBillCode}</if> <if test="paymentBillCode != null and paymentBillCode != ''"> and payment_bill_code = #{paymentBillCode}</if>
<if test="paymentBillCodeList != null and paymentBillCodeList.size>0"> and payment_bill_code in
<foreach index="index" collection="paymentBillCodeList" item="paymentBillCode" separator="," open="(" close=")">
#{paymentBillCode}
</foreach>
</if>
<if test="vendorCode != null and vendorCode != ''"> and vendor_code = #{vendorCode}</if> <if test="vendorCode != null and vendorCode != ''"> and vendor_code = #{vendorCode}</if>
</where> </where>
</select> </select>

View File

@ -96,30 +96,57 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectOmsPayableBillList" parameterType="OmsPayableBill" resultMap="OmsPayableBillResult"> <select id="selectOmsPayableBillList" parameterType="OmsPayableBill" resultMap="OmsPayableBillResult">
<include refid="selectOmsPayableBillRelationVo"/> <include refid="selectOmsPayableBillRelationVo"/>
<where> <where>
<if test="payableBillCode != null and payableBillCode != ''"> and t1.payable_bill_code like concat( #{payableBillCode},'%') </if> <if test="payableBillCode != null and payableBillCode != ''">and t1.payable_bill_code like concat(
<if test="idList != null and idList.size>0"> and t1.id in <foreach item="item" collection="idList" separator="," open="(" close=")" index="">#{item}</foreach></if> #{payableBillCode},'%')
<if test="vendorCode != null and vendorCode != ''"> and t1.vendor_code = #{vendorCode}</if> </if>
<if test="vendorName != null and vendorName != ''"> and t4.vendor_name = #{vendorName}</if> <if test="idList != null and idList.size>0">and t1.id in
<if test="projectCode != null and projectCode != ''"> and t3.project_code = #{projectCode}</if> <foreach item="item" collection="idList" separator="," open="(" close=")" index="">#{item}</foreach>
<if test="projectName != null and projectName != ''"> and t3.project_name = #{projectName}</if> </if>
<if test="orderCode != null and orderCode != ''"> and t1.order_code like concat( #{orderCode},'%') </if> <if test="vendorCode != null and vendorCode != ''">and t1.vendor_code = #{vendorCode}</if>
<if test="inventoryCode != null and inventoryCode != ''"> and t1.inventory_code like concat( #{inventoryCode},'%') </if> <if test="vendorName != null and vendorName != ''">and t4.vendor_name = #{vendorName}</if>
<if test="productType != null and productType != ''"> and t1.product_type = #{productType}</if> <if test="projectCode != null and projectCode != ''">and t3.project_code = #{projectCode}</if>
<if test="totalPriceWithTax != null "> and t1.total_price_with_tax = #{totalPriceWithTax}</if> <if test="projectName != null and projectName != ''">and t3.project_name = #{projectName}</if>
<if test="totalPriceWithoutTax != null "> and t1.total_price_without_tax = #{totalPriceWithoutTax}</if> <if test="orderCode != null and orderCode != ''">and t1.order_code like concat( #{orderCode},'%')</if>
<if test="taxAmount != null "> and t1.tax_amount = #{taxAmount}</if> <if test="inventoryCode != null and inventoryCode != ''">and t1.inventory_code like concat(
<if test="paidPaymentAmount != null "> and t1.paid_payment_amount = #{paidPaymentAmount}</if> #{inventoryCode},'%')
<if test="unpaidPaymentAmount != null "> and t1.unpaid_payment_amount = #{unpaidPaymentAmount}</if> </if>
<if test="receivedTicketAmount != null "> and t1.received_ticket_amount = #{receivedTicketAmount}</if> <if test="productType != null and productType != ''">and t1.product_type = #{productType}</if>
<if test="unreceivedTicketAmount != null "> and t1.unreceived_ticket_amount = #{unreceivedTicketAmount}</if> <if test="totalPriceWithTax != null ">and t1.total_price_with_tax = #{totalPriceWithTax}</if>
<if test="lastPaymentPlanId != null"> and t1.last_payment_plan_id = #{lastPaymentPlanId}</if> <if test="totalPriceWithoutTax != null ">and t1.total_price_without_tax = #{totalPriceWithoutTax}</if>
<if test="lastTicketPlanId != null"> and t1.last_ticket_plan_id = #{lastTicketPlanId}</if> <if test="taxAmount != null ">and t1.tax_amount = #{taxAmount}</if>
<if test="planPaymentDate != null "> and ppp.plan_payment_date = #{planPaymentDate}</if> <if test="paidPaymentAmount != null ">and t1.paid_payment_amount = #{paidPaymentAmount}</if>
<if test="planAmount != null "> and ppp.plan_amount = #{planAmount}</if> <if test="unpaidPaymentAmount != null ">
<choose>
<when test="unpaidPaymentAmount==-1">
and t1.unpaid_payment_amount != 0
</when>
<otherwise>
and t1.unpaid_payment_amount = #{unpaidPaymentAmount}
</otherwise>
</choose>
</if>
<if test="receivedTicketAmount != null ">and t1.received_ticket_amount = #{receivedTicketAmount}</if>
<if test="unreceivedTicketAmount != null ">
<choose>
<when test="unreceivedTicketAmount==-1">
and t1.unreceived_ticket_amount != 0
</when>
<otherwise>
and t1.unreceived_ticket_amount = #{unreceivedTicketAmount}
</otherwise>
</choose>
</if>
<if test="lastPaymentPlanId != null">and t1.last_payment_plan_id = #{lastPaymentPlanId}</if>
<if test="lastTicketPlanId != null">and t1.last_ticket_plan_id = #{lastTicketPlanId}</if>
<if test="planPaymentDate != null ">and ppp.plan_payment_date = #{planPaymentDate}</if>
<if test="planAmount != null ">and ppp.plan_amount = #{planAmount}</if>
<if test="createTimeStart != null or createTimeEnd != null"> <if test="createTimeStart != null or createTimeEnd != null">
<choose> <choose>
<when test="createTimeStart != null and createTimeEnd != null"> <when test="createTimeStart != null and createTimeEnd != null">
and t1.create_time between date_format(#{createTimeStart}, '%Y-%m-%d 00:00:00') and date_format(#{createTimeEnd}, '%Y-%m-%d 23:59:59') and t1.create_time between date_format(#{createTimeStart}, '%Y-%m-%d 00:00:00') and
date_format(#{createTimeEnd}, '%Y-%m-%d 23:59:59')
</when> </when>
<when test="createTimeStart != null"> <when test="createTimeStart != null">
and t1.create_time <![CDATA[ >= ]]> date_format(#{createTimeStart}, '%Y-%m-%d 00:00:00') and t1.create_time <![CDATA[ >= ]]> date_format(#{createTimeStart}, '%Y-%m-%d 00:00:00')
@ -133,13 +160,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="planPaymentDateStart != null or planPaymentDateEnd != null"> <if test="planPaymentDateStart != null or planPaymentDateEnd != null">
<choose> <choose>
<when test="planPaymentDateStart != null and planPaymentDateEnd != null"> <when test="planPaymentDateStart != null and planPaymentDateEnd != null">
and ppp.plan_payment_date between date_format(#{planPaymentDateStart}, '%Y-%m-%d 00:00:00') and date_format(#{planPaymentDateEnd}, '%Y-%m-%d 23:59:59') and ppp.plan_payment_date between date_format(#{planPaymentDateStart}, '%Y-%m-%d 00:00:00') and
date_format(#{planPaymentDateEnd}, '%Y-%m-%d 23:59:59')
</when> </when>
<when test="planPaymentDateStart != null"> <when test="planPaymentDateStart != null">
and ppp.plan_payment_date <![CDATA[ >= ]]> date_format(#{planPaymentDateStart}, '%Y-%m-%d 00:00:00') and ppp.plan_payment_date <![CDATA[ >= ]]> date_format(#{planPaymentDateStart}, '%Y-%m-%d
00:00:00')
</when> </when>
<when test="planPaymentDateEnd != null"> <when test="planPaymentDateEnd != null">
and ppp.plan_payment_date <![CDATA[ <= ]]> date_format(#{planPaymentDateEnd}, '%Y-%m-%d 23:59:59') and ppp.plan_payment_date <![CDATA[ <= ]]> date_format(#{planPaymentDateEnd}, '%Y-%m-%d
23:59:59')
</when> </when>
</choose> </choose>
</if> </if>

View File

@ -11,6 +11,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="paymentStatus" column="payment_status" /> <result property="paymentStatus" column="payment_status" />
<result property="paymentTime" column="payment_time" /> <result property="paymentTime" column="payment_time" />
<result property="paymentAmount" column="payment_amount" /> <result property="paymentAmount" column="payment_amount" />
<result property="paymentAmountWithoutTax" column="payment_amount_without_tax" />
<result property="paymentAmountTax" column="payment_amount_tax" />
<result property="writeOffId" column="write_off_id" />
<result property="paymentRate" column="payment_rate" /> <result property="paymentRate" column="payment_rate" />
<result property="paymentBillCode" column="payment_bill_code" /> <result property="paymentBillCode" column="payment_bill_code" />
<result property="remark" column="remark" /> <result property="remark" column="remark" />
@ -25,6 +28,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="payableBillId != null">payable_bill_id,</if> <if test="payableBillId != null">payable_bill_id,</if>
<if test="paymentTime != null">payment_time,</if> <if test="paymentTime != null">payment_time,</if>
<if test="paymentAmount != null">payment_amount,</if> <if test="paymentAmount != null">payment_amount,</if>
<if test="paymentAmountWithoutTax != null">payment_amount_without_tax,</if>
<if test="paymentAmountTax != null">payment_amount_tax,</if>
<if test="writeOffId != null">write_off_id,</if>
<if test="paymentRate != null">payment_rate,</if> <if test="paymentRate != null">payment_rate,</if>
<if test="paymentBillCode != null and paymentBillCode != ''">payment_bill_code,</if> <if test="paymentBillCode != null and paymentBillCode != ''">payment_bill_code,</if>
<if test="payableDetailType != null and payableDetailType != ''">payable_detail_type,</if> <if test="payableDetailType != null and payableDetailType != ''">payable_detail_type,</if>
@ -36,6 +42,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="payableBillId != null">#{payableBillId},</if> <if test="payableBillId != null">#{payableBillId},</if>
<if test="paymentTime != null">#{paymentTime},</if> <if test="paymentTime != null">#{paymentTime},</if>
<if test="paymentAmount != null">#{paymentAmount},</if> <if test="paymentAmount != null">#{paymentAmount},</if>
<if test="paymentAmountWithoutTax != null">#{paymentAmountWithoutTax},</if>
<if test="paymentAmountTax != null">#{paymentAmountTax},</if>
<if test="writeOffId != null">#{writeOffId},</if>
<if test="paymentRate != null">#{paymentRate},</if> <if test="paymentRate != null">#{paymentRate},</if>
<if test="paymentBillCode != null and paymentBillCode != ''">#{paymentBillCode},</if> <if test="paymentBillCode != null and paymentBillCode != ''">#{paymentBillCode},</if>
<if test="payableDetailType != null and payableDetailType != ''">#{payableDetailType},</if> <if test="payableDetailType != null and payableDetailType != ''">#{payableDetailType},</if>
@ -46,12 +55,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</insert> </insert>
<insert id="insertBatch"> <insert id="insertBatch">
insert into oms_payable_payment_detail ( insert into oms_payable_payment_detail (
payment_plan_id, payable_bill_id, payment_time, payment_amount, payment_rate, payment_plan_id, payable_bill_id, payment_time, payment_amount, payment_amount_without_tax,
payment_bill_code, payable_detail_type, remark, create_by, create_time ) payment_amount_tax, write_off_id, payment_rate, payment_bill_code, payable_detail_type, remark,
create_by, create_time )
values values
<foreach item="item" collection="list" separator="," index=""> <foreach item="item" collection="list" separator="," index="">
(#{item.paymentPlanId},#{item.payableBillId},#{item.paymentTime},#{item.paymentAmount}, (#{item.paymentPlanId},#{item.payableBillId},#{item.paymentTime},#{item.paymentAmount},#{item.paymentAmountWithoutTax},
#{item.paymentRate},#{item.paymentBillCode},#{item.payableDetailType},#{item.remark}, #{item.paymentAmountTax},#{item.writeOffId},#{item.paymentRate},#{item.paymentBillCode},#{item.payableDetailType},#{item.remark},
#{item.createBy}, #{item.createBy},
sysdate()) sysdate())
</foreach> </foreach>
@ -77,12 +87,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach> </foreach>
</if> </if>
</where> </where>
order by t1.create_time desc
</select> </select>
<select id="selectByPaymentPlanIds" resultType="com.ruoyi.sip.domain.OmsPayablePaymentDetail"> <select id="selectByPaymentPlanIds" resultType="com.ruoyi.sip.domain.OmsPayablePaymentDetail">
SELECT SELECT
t1.id, t1.payment_plan_id, t1.payable_bill_id, t1.payment_time, t1.id, t1.payment_plan_id, t1.payable_bill_id, t1.payment_time,
t1.payment_amount, t1.payment_rate, t1.payment_bill_code, t1.remark, t1.payment_amount, t1.payment_amount_without_tax, t1.payment_amount_tax, t1.write_off_id, t1.payment_rate, t1.payment_bill_code, t1.remark,
t1.create_time, t1.create_by, t1.update_time, t1.payable_detail_type t1.create_time, t1.create_by, t1.update_time, t1.payable_detail_type
FROM FROM
oms_payable_payment_detail t1 oms_payable_payment_detail t1

View File

@ -111,29 +111,56 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectOmsPaymentBillList" parameterType="OmsPaymentBill" resultMap="OmsPaymentBillResult"> <select id="selectOmsPaymentBillList" parameterType="OmsPaymentBill" resultMap="OmsPaymentBillResult">
<include refid="selectOmsPaymentBillVo"/> <include refid="selectOmsPaymentBillVo"/>
<where> <where>
<if test="paymentBillCode != null and paymentBillCode != ''"> and pb.payment_bill_code like concat('%', #{paymentBillCode}, '%')</if> <if test="paymentBillCode != null and paymentBillCode != ''">and pb.payment_bill_code like concat('%',
<if test="paymentBillType != null and paymentBillType != ''"> and pb.payment_bill_type = #{paymentBillType}</if> #{paymentBillCode}, '%')
<if test="paymentTime != null "> and date_format(pb.payment_time,'%Y-%m-%d') = date_format(#{paymentTime},'%Y-%m-%d')</if> </if>
<if test="vendorCode != null and vendorCode != ''"> and pb.vendor_code like concat('%', #{vendorCode}, '%')</if> <if test="paymentBillType != null and paymentBillType != ''">and pb.payment_bill_type =
<if test="orderCode != null and orderCode != ''"> and pb.order_code like concat('%', #{orderCode}, '%')</if> #{paymentBillType}
<if test="totalPriceWithTax != null "> and pb.total_price_with_tax = #{totalPriceWithTax}</if> </if>
<if test="totalPriceWithoutTax != null "> and pb.total_price_without_tax = #{totalPriceWithoutTax}</if> <if test="paymentTime != null ">and date_format(pb.payment_time,'%Y-%m-%d') =
<if test="taxAmount != null "> and pb.tax_amount = #{taxAmount}</if> date_format(#{paymentTime},'%Y-%m-%d')
<if test="projectCode != null and projectCode != ''"> and pb.project_code like concat('%', #{projectCode}, '%')</if> </if>
<if test="projectName != null and projectName != ''"> and pb.project_name like concat('%', #{projectName}, '%')</if> <if test="vendorCode != null and vendorCode != ''">and pb.vendor_code like concat('%', #{vendorCode},
<if test="paymentStatus != null and paymentStatus != ''"> and pb.payment_status = #{paymentStatus}</if> '%')
<if test="approveStatus != null and approveStatus != ''"> and pb.approve_status = #{approveStatus}</if> </if>
<if test="approveNode != null and approveNode != ''"> and pb.approve_node = #{approveNode}</if> <if test="orderCode != null and orderCode != ''">and pb.order_code like concat('%', #{orderCode}, '%')</if>
<if test="approveTime != null "> and date_format(pb.approve_time,'%Y-%m-%d') = date_format(#{approveTime},'%Y-%m-%d')</if> <if test="totalPriceWithTax != null ">and pb.total_price_with_tax = #{totalPriceWithTax}</if>
<if test="actualPaymentTime != null "> and date_format(pb.actual_payment_time,'%Y-%m-%d') = date_format(#{actualPaymentTime},'%Y-%m-%d')</if> <if test="totalPriceWithoutTax != null ">and pb.total_price_without_tax = #{totalPriceWithoutTax}</if>
<if test="paymentMethod != null and paymentMethod != ''"> and pb.payment_method = #{paymentMethod}</if> <if test="taxAmount != null ">and pb.tax_amount = #{taxAmount}</if>
<if test="payableBillCode != null and payableBillCode != ''"> and apb.payable_bill_code like concat('%', #{payableBillCode}, '%')</if> <if test="projectCode != null and projectCode != ''">and pb.project_code like concat('%', #{projectCode},
'%')
</if>
<if test="projectName != null and projectName != ''">and pb.project_name like concat('%', #{projectName},
'%')
</if>
<if test="paymentStatus != null and paymentStatus != ''">and pb.payment_status = #{paymentStatus}</if>
<if test="approveStatus != null and approveStatus != ''">and pb.approve_status = #{approveStatus}</if>
<if test="approveNode != null and approveNode != ''">and pb.approve_node = #{approveNode}</if>
<if test="approveTime != null ">and date_format(pb.approve_time,'%Y-%m-%d') =
date_format(#{approveTime},'%Y-%m-%d')
</if>
<if test="actualPaymentTime != null ">and date_format(pb.actual_payment_time,'%Y-%m-%d') =
date_format(#{actualPaymentTime},'%Y-%m-%d')
</if>
<if test="paymentMethod != null and paymentMethod != ''">and pb.payment_method = #{paymentMethod}</if>
<if test="payableBillCode != null and payableBillCode != ''">and apb.payable_bill_code like concat('%',
#{payableBillCode}, '%')
</if>
<if test="preResidueAmount != null and preResidueAmount != ''">
<choose>
<when test="preResidueAmount == -1">
and pb.pre_residue_amount != 0
</when>
<when test="preResidueAmount !== -1">
and pb.pre_residue_amount = #{preResidueAmount}
</when>
</choose>
</if>
and pb.del_flag = '0' and pb.del_flag = '0'
</where> </where>
group by pb.id
order by pb.create_time desc order by pb.create_time desc
</select> </select>
<select id="selectOmsPaymentBillById" parameterType="Long" resultMap="OmsPaymentBillResult"> <select id="selectOmsPaymentBillById" parameterType="Long" resultMap="OmsPaymentBillResult">
<include refid="selectOmsPaymentBillVo"/> <include refid="selectOmsPaymentBillVo"/>
where pb.id = #{id} where pb.id = #{id}