feat(finance): 新增收款与核销功能模块

- 实现销售应收单详情查看与编辑功能
- 添加合并收款单与开票单发起流程
- 开发手动核销应付单与付款单功能
- 支持应付计划选择与核销金额计算
- 增加税务相关金额计算逻辑
dev_1.0.1
chenhao 2025-12-17 11:15:10 +08:00
parent 6613b3612c
commit 8d6ca0b64f
61 changed files with 7660 additions and 1 deletions

View File

@ -0,0 +1,245 @@
<template>
<el-drawer title="修改销售应收单" :visible.sync="internalVisible" size="70%" @close="handleClose">
<div class="dialog-body">
<!-- Part 1: Details -->
<div>
<el-divider content-position="left">销售-应收单</el-divider>
<div class="details-container">
<el-row :gutter="20">
<el-col :span="8">
<div class="detail-item"><strong>应收单编号:</strong> {{ formData.receivableBillCode }}</div>
</el-col>
<el-col :span="16">
<div class="detail-item"><strong>生成时间:</strong> {{ formData.createTime }}</div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<div class="detail-item"><strong>进货商名称:</strong> {{ formData.partnerName }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>项目编号:</strong> {{ formData.projectCode }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>项目名称:</strong> {{ formData.projectName }}</div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<div class="detail-item"><strong>合同编号:</strong> {{ formData.orderCode }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>出入库单号:</strong> {{ formData.inventoryCode }}</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>
<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-row>
<el-row :gutter="20">
<el-col :span="8">
<div class="detail-item"><strong>未收款金额:</strong> {{ formData.unreceivedAmount }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>已收款金额:</strong> {{ formData.receivedAmount }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>收款中金额:</strong> {{ this.$calc.sub(this.$calc.sub(formData.totalPriceWithTax,formData.receivedAmount),formData.unreceivedAmount) }}</div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<div class="detail-item"><strong>未开票金额:</strong> {{ formData.uninvoicedAmount }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>已开票金额:</strong> {{ formData.invoicedAmount }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item"><strong>开票中金额:</strong> {{ this.$calc.sub(this.$calc.sub(formData.totalPriceWithTax,formData.invoicedAmount),formData.uninvoicedAmount)}}</div>
</el-col>
</el-row>
</div>
</div>
<!-- Part 2: Tabs -->
<div style="padding: 20px">
<el-tabs v-model="activeTab">
<el-tab-pane label="明细" name="details">
<el-divider content-position="left">销售收款单</el-divider>
<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 prop="receivableDetailType" label="收款通道">
<template slot-scope="scope">
<dict-tag :options="dict.type.receivable_detail_type" :value="scope.row.receivableDetailType"/>
</template>
</el-table-column>
<el-table-column prop="actualReceiptTime" label="实际收款时间">
<template slot-scope="scope">
{{ scope.row.actualReceiptTime || '-' }}
</template>
</el-table-column>
<el-table-column prop="receiptAmount" label="本次收款金额"></el-table-column>
<el-table-column prop="receiptRate" label="本次收款比例"></el-table-column>
<el-table-column prop="collectionStatus" label="收款状态">
<template slot-scope="scope">
<dict-tag :options="dict.type.collection_status" :value="scope.row.collectionStatus"/>
</template>
</el-table-column>
<el-table-column prop="receiptBillCode" label="销售收款单编号"></el-table-column>
<el-table-column label="回执单/退款图">
<template slot-scope="scope">
{{ scope.row.finAttachment && scope.row.finAttachment.fileName || '-'}}
<el-button v-show="scope.row.finAttachment" type="primary" size="mini" @click="downloadFile(scope.row.finAttachment)"></el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="收款计划" name="receiptPlan">
<ReceiptPlan :isInitEdit=true @syncPlan="refreshInvoicePlan()" :receivableData="data"/>
</el-tab-pane>
<el-tab-pane label="开票计划" name="invoicePlan">
<InvoicePlan ref="invoicePlan" :isInitEdit=true :receivableData="data"/>
</el-tab-pane>
</el-tabs>
</div>
</div>
<!-- <div slot="footer" class="dialog-footer">-->
<!-- <el-button @click="handleClose"> </el-button>-->
<!-- <el-button type="primary" @click="handleSubmit"> </el-button>-->
<!-- </div>-->
</el-drawer>
</template>
<script>
import ReceiptPlan from './ReceiptPlan.vue';
import InvoicePlan from './InvoicePlan.vue';
import { getReceivable } from "@/api/finance/receivable";
export default {
name: "EditForm",
dicts: ['product_type','collection_status','receivable_detail_type'],
components: {
ReceiptPlan,
InvoicePlan
},
props: {
visible: {
type: Boolean,
default: false
},
data: {
type: Object,
default: () => ({})
}
},
data() {
return {
internalVisible: this.visible, // Local copy of the visible prop
activeTab: 'details',
formData: {}
};
},
watch: {
visible(newVal) {
this.internalVisible = newVal; // Sync prop to local data
if (newVal && this.data.id) {
this.getDetails();
}
},
internalVisible(newVal) {
if (!newVal) {
this.formData = {};
}
this.$emit('update:visible', newVal); // Emit changes to parent
}
},
methods: {
getDetails() {
getReceivable(this.data.id).then(res => {
this.formData = res.data;
});
},
refreshInvoicePlan(){
this.$refs.invoicePlan.fetchInvoicePlans(this.formData.id);
},
downloadFile(attachment){
if (attachment){
const link = document.createElement('a');
link.href = process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" +attachment.filePath;
link.download = attachment.fileName || 'receipt';
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
},
getSummaries(param) {
const { columns, data } = param;
const sums = [];
let receiptAmountSum = 0;
if (data && data.length > 0) {
receiptAmountSum = data.reduce((acc, item) => {
const value = Number(item.receiptAmount);
return acc + (isNaN(value) ? 0 : value);
}, 0);
}
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '合计';
} else if (column.property === 'receiptAmount') {
sums[index] = receiptAmountSum.toFixed(2);
} else if (column.property === 'receiptRate') {
if (this.formData.totalPriceWithTax && this.formData.totalPriceWithTax > 0) {
const ratio = this.$calc.div(receiptAmountSum , this.formData.totalPriceWithTax,4);
sums[index] = (ratio * 100).toFixed(2) + '%';
} else {
sums[index] = '0.00%';
}
} else {
sums[index] = '';
}
});
return sums;
},
handleClose() {
this.internalVisible = false; // Close dialog locally
},
handleSubmit() {
this.handleClose();
},
}
};
</script>
<style scoped>.details-container {
border: 1px solid #EBEEF5;
padding: 20px;
border-radius: 4px;
}
.detail-item {
border: 1px solid #EBEEF5;
padding: 10px;
border-radius: 4px;
margin-bottom: 10px;
font-size: 14px;
}
.dialog-body {
overflow-y: auto;
}
</style>

View File

@ -0,0 +1,293 @@
<template>
<div class="dialog-body">
<el-divider content-position="left">开票计划</el-divider>
<el-button v-if="isEditing" type="primary" size="mini" @click="handleSaveInvoicePlan"
style="margin-bottom: 10px;">
保存开票计划
</el-button>
<el-button v-else type="primary" size="mini" @click="isEditing=true"
style="margin-bottom: 10px;">
编辑
</el-button>
<el-table :data="invoicePlans" border @selection-change="selectPlan" ref="invoicePlanTable">
<el-table-column type="selection" width="50" align="center" :selectable="selectableRow"/>
<el-table-column label="序号" type="index" width="50" align="center"></el-table-column>
<el-table-column label="预计开票时间" align="center" width="200">
<template slot-scope="scope">
<el-date-picker v-model="scope.row.planInvoiceDate" type="date" style="width: 180px"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期"
:disabled="!isEditing || isNumberStr(scope.row.detailId)"></el-date-picker>
</template>
</el-table-column>
<el-table-column label="预计开票金额" align="center" width="230">
<template slot-scope="scope">
<el-input-number
v-model="scope.row.planAmount"
:precision="2"
:step="100"
:min="0.01"
:readonly="!scope.row.detailId"
:max="totalPriceWithTax"
@change="handleAmountChange(scope.row)"
:disabled="!isEditing || isNumberStr(scope.row.detailId)"
></el-input-number>
</template>
</el-table-column>
<el-table-column label="开票比例(%)" align="center" width="230">
<template slot-scope="scope">
<el-input-number
v-model="scope.row.planRate"
:precision="2"
:step="1"
:min="0.01"
:max="100"
:readonly="!scope.row.detailId"
@change="handleRateChange(scope.row)"
:disabled="!isEditing || isNumberStr(scope.row.detailId)"
></el-input-number>
</template>
</el-table-column>
<el-table-column label="备注" align="center">
<template slot-scope="scope">
<el-input v-model="scope.row.remark" placeholder="请输入备注"
:disabled="!isEditing || isNumberStr(scope.row.detailId)"></el-input>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="150" fixed="right">
<template slot-scope="scope">
<el-button v-if="isEditing && !isNumberStr(scope.row.detailId)"
size="mini"
type="text"
icon="el-icon-plus"
@click="handleAddInvoicePlanRow"
>增加下行
</el-button>
<el-button v-if="isEditing && !isNumberStr(scope.row.detailId)"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDeleteInvoicePlanRow(scope.$index)"
:disabled="invoicePlans.length === 1 || scope.row.status === 'invoiced'"
>删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import {getInvoicePlan, updateInvoicePlan} from "@/api/finance/receivable";
import {isNumberStr} from "@/utils";
export default {
name: "InvoicePlan",
props: {
receivableData: {
type: Object,
default: () => {
}
},
isInitEdit: {
type: Boolean,
default: false
},
selectedPlans: {
type: Array,
default: () => []
}
},
data() {
return {
selectedPlan:[],
isEditing: false,
loading: false,
invoicePlans: [],
};
},
computed: {
title() {
return `选择开票计划 - ${this.receivableData.receivableBillCode}`;
},
totalPlannedAmount() {
return this.invoicePlans.reduce((sum, plan) => sum + (plan.planAmount || 0), 0);
},
totalUninvoicedAmount() {
return this.receivableData.uninvoicedAmount || 0;
},
totalPriceWithTax() {
return this.receivableData.totalPriceWithTax || 0;
}
},
watch: {
'receivableData.id': {
handler(newVal, oldVal) {
if (newVal) {
this.fetchInvoicePlans(newVal)
}
},
immediate: true
},
isInitEdit: {
handler(newVal) {
if (newVal) {
this.isEditing = newVal
}
},
immediate: true
}
},
methods: {
isNumberStr,
selectableRow(row, index){
return !row.detailId;
},
selectPlan( selection){
this.selectedPlan=selection
},
fetchInvoicePlans(receivableId) {
if (this.receivableData && receivableId) {
getInvoicePlan(receivableId).then(response => {
this.invoicePlans = response.data.map(item => ({
...item,
status: item.status || 'pending'
}));
if (this.invoicePlans.length === 0) {
this.initDefaultInvoicePlan();
} else {
this.$nextTick(() => {
this.invoicePlans.forEach(plan => {
const isSelected = this.selectedPlans.some(selected => selected.id === plan.id);
if (isSelected) {
this.$refs.invoicePlanTable.toggleRowSelection(plan, true);
}
});
});
}
})
} else {
this.initDefaultInvoicePlan();
}
},
initDefaultInvoicePlan() {
this.invoicePlans = [{
planInvoiceDate: null,
planAmount: this.totalPriceWithTax,
planRate: 100,
remark: '',
status: 'pending'
}];
},
handleSaveInvoicePlan() {
if (!this.validateInvoicePlans()) {
return;
}
if (!this.validateInvoicePlanTotals()) {
return;
}
for (let i = 0; i < this.invoicePlans.length; i++) {
const plan = this.invoicePlans[i];
if (!plan.planInvoiceDate) {
this.$modal.msgError(`${i + 1} 行开票计划的预计开票时间不能为空。`);
return;
}
if (plan.planAmount === null || plan.planAmount === undefined || plan.planAmount === '' || plan.planAmount < 0) {
this.$modal.msgError(`${i + 1} 行开票计划的预计开票金额不能为空。`);
return;
}
if (plan.planRate === null || plan.planRate === undefined || plan.planRate === '') {
this.$modal.msgError(`${i + 1} 行开票计划的开票比例不能为空。`);
return;
}
}
updateInvoicePlan(this.receivableData.id, this.invoicePlans).then(() => {
this.$modal.msgSuccess("保存成功");
this.fetchInvoicePlans(this.receivableData.id);
});
},
handleAddInvoicePlanRow() {
this.invoicePlans.push({
planInvoiceDate: null,
planAmount: 0,
planRate: 0,
remark: '',
status: 'pending'
});
},
handleDeleteInvoicePlanRow(index) {
if (this.invoicePlans.length === 1) {
this.$modal.msgError("至少需要保留一条开票计划。");
return;
}
if (this.invoicePlans[index].status === 'invoiced') {
this.$modal.msgError("已开票的计划不能删除。");
return;
}
this.invoicePlans.splice(index, 1);
},
handleAmountChange(row) {
if (this.totalPriceWithTax === 0) {
row.planRate = 0;
return;
}
row.planRate = this.$calc.mul((this.$calc.div(row.planAmount, this.totalPriceWithTax,4)), 100);
},
handleRateChange(row) {
row.planAmount = this.$calc.div(this.$calc.mul(this.totalPriceWithTax , row.planRate),100);
},
validateInvoicePlanTotals() {
const totalAmount = this.invoicePlans.reduce((sum, plan) => sum + (plan.planAmount || 0), 0);
if (totalAmount !== this.totalPriceWithTax) {
this.$modal.msgError(`预计开票金额之和应该等于应收总金额[${this.totalPriceWithTax}]`);
return false;
}
return true;
},
validateInvoicePlans() {
if (this.invoicePlans.length === 0) {
this.$modal.msgError("请至少添加一条开票计划。");
return false;
}
for (let i = 0; i < this.invoicePlans.length; i++) {
const plan = this.invoicePlans[i];
if (!plan.planInvoiceDate) {
this.$modal.msgError(`${i + 1} 行开票计划的预计开票时间不能为空。`);
return false;
}
if (plan.planAmount === null || plan.planAmount === undefined || plan.planAmount <= 0) {
this.$modal.msgError(`${i + 1} 行开票计划的预计开票金额必须大于0。`);
return false;
}
if (plan.planRate === null || plan.planRate === undefined || plan.planRate === '') {
this.$modal.msgError(`${i + 1} 行开票计划的开票比例不能为空。`);
return false;
}
}
return true;
}
}
};
</script>
<style scoped>
.dialog-body {
max-height: 70vh;
overflow-y: auto;
padding-right: 10px; /* To prevent scrollbar from overlapping content */
}
.total-info {
margin-top: 20px;
text-align: right;
font-weight: bold;
}
</style>

View File

@ -0,0 +1,352 @@
<template>
<el-dialog title="合并发起开票单" :visible.sync="dialogVisible" width="80%" @close="handleClose" append-to-body>
<div class="dialog-body">
<el-form ref="form" :model="form" :inline="true" label-width="120px">
<el-row>
<el-col :span="8">
<el-form-item label="开票单类型" prop="invoiceBillType">
<el-select disabled v-model="form.invoiceBillType" placeholder="请选择开票单类型" clearable>
<el-option
v-for="dict in dict.type.receipt_bill_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="客户名称">
<el-input v-model="form.customerName" readonly/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="预计开票时间" prop="invoiceTime">
<el-date-picker
v-model="form.invoiceTime"
type="date"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期"
></el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider content-position="left">销售应收单表</el-divider>
<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="planInvoiceDate" width="180"/>
<el-table-column label="开票计划" align="center" width="100" prop="planInvoiceAmount">
</el-table-column>
<el-table-column label="合同编号" align="center" prop="orderCode" width="150"/>
<el-table-column label="出入库单号" align="center" prop="inventoryCode" width="150"/>
<!-- <el-table-column label="开票状态" align="center" prop="invoiceStatus" width="120">
<template slot-scope="scope">
<dict-tag :options="dict.type.invoice_status" :value="scope.row.invoiceStatus"/>
</template>
</el-table-column> -->
<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" 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" class-name="small-padding fixed-width" width="100" fixed="right">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleOpenInvoicePlanSelector(scope.row, scope.$index)"
>选择
</el-button>
</template>
</el-table-column>
</el-table>
<div class="total-info">
<span style="margin-left: 20px;">计划开票总金额: <el-tag type="success">{{
totalPlannedAmount.toFixed(2)
}}</el-tag></span>
<span>计划开票比例: <el-tag type="info">{{ this.$calc.mul(this.$calc.div(totalPlannedAmount,totalReceivableAmountWithTax,4),100) }}%</el-tag></span>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="handleCancel"> </el-button>
<el-button type="primary" @click="handleConfirm"> </el-button>
</div>
<el-dialog :title="planTitle" :visible.sync="isInvoicePlanSelectorOpen" width="70%"
@close="isInvoicePlanSelectorOpen=false" append-to-body>
<invoice-plan
ref="planSelector"
:receivable-data="chooseReceivable"
:selected-plans="chooseReceivable.invoicePlans"
@confirm="handleInvoicePlanConfirm"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="isInvoicePlanSelectorOpen=false"> </el-button>
<!-- <el-button type="primary" @click="handleConfirm" > </el-button>-->
<el-button type="primary" @click="handleChooseConfirm"> </el-button>
</div>
</el-dialog>
<!-- 开票计划选择器弹窗 -->
</el-dialog>
</template>
<script>
import InvoicePlan from './InvoicePlan.vue';
export default {
name: "MergeInvoiceDialog",
components: {InvoicePlan},
dicts: ['invoice_status','receipt_bill_type'], // Add dicts for dict-tag
props: {
visible: {
type: Boolean,
default: false
},
receivableBills: {
type: Array,
default: () => []
}
},
data() {
return {
internalVisible: this.visible,
planTitle: '',
chooseReceivable: {},
form: {
invoiceBillType: 'FROM_RECEIVABLE', // Default to a type
customerName: '',
invoiceTime: null,
},
receivableBillsWithPlans: [], // Each order will now have its own invoicePlans array
isInvoicePlanSelectorOpen: false,
currentReceivableBillIndexForPlan: -1, // Index of the order in receivableBillsWithPlans
loadingInvoicePlans: false, // Loading state for fetching invoice plans
};
},
computed: {
dialogVisible: {
get() {
return this.internalVisible;
},
set(val) {
this.internalVisible = val;
this.$emit('update:visible', val);
}
},
totalReceivableAmountWithTax() {
return this.receivableBillsWithPlans.reduce((sum, order) => sum + (order.totalPriceWithTax || 0), 0);
},
totalPlannedAmount() {
return this.receivableBillsWithPlans.reduce((orderSum, order) => {
const orderPlansTotal = (order.invoicePlans || []).reduce((planSum, plan) => planSum + (plan.planAmount || 0), 0);
return orderSum + orderPlansTotal;
}, 0);
},
},
watch: {
visible(newVal) {
this.internalVisible = newVal;
if (newVal) {
this.initDialogData();
}
},
receivableBills: {
handler(newVal) {
if (this.dialogVisible) {
this.initDialogData();
}
},
deep: true
}
},
methods: {
initDialogData() {
// Initialize form fields
if (this.receivableBills.length > 0) {
const firstCustomerName = this.receivableBills[0].customerName;
const allSameCustomer = this.receivableBills.every(order => order.customerName === firstCustomerName);
this.form.customerName = allSameCustomer ? firstCustomerName : '多个客户';
this.form.invoiceTime = null; // Reset time
} else {
this.form.customerName = '';
this.form.invoiceTime = null;
}
this.form.invoiceBillType = 'FROM_RECEIVABLE'; // Default
// Initialize receivableBillsWithPlans
this.receivableBillsWithPlans = this.receivableBills.map(order => {
const invoicePlans = order.invoicePlans ? [...order.invoicePlans] : [];
if (invoicePlans.length === 0 && order.lastInvoicePlanId) {
invoicePlans.push({
id: order.lastInvoicePlanId,
planAmount: order.planInvoiceAmount,
planInvoiceDate: order.planInvoiceDate,
planRate: this.$calc.mul(this.$calc.div(order.planInvoiceAmount, order.totalPriceWithTax, 4), 100)
});
}
return {
...order,
invoicePlans: invoicePlans, // Retain existing plans if any, otherwise empty
totalPriceWithTax: order.totalPriceWithTax || 0, // Ensure numeric for calculations
uninvoicedAmount: order.uninvoicedAmount || 0,
invoicedAmount: order.invoicedAmount || 0, // Ensure numeric for calculations
}
});
},
handleClose() {
this.dialogVisible = false;
this.resetForm();
},
handleChooseConfirm() {
if (!this.$refs.planSelector) {
this.$modal.msgError('无法获取计划选择器组件');
return;
}
const selectedPlans = this.$refs.planSelector.selectedPlan || [];
const orderIndex = this.receivableBillsWithPlans.findIndex(o => o.id === this.chooseReceivable.id);
if (orderIndex === -1) {
this.$modal.msgError('找不到要更新的应收单');
return;
}
const currentOrder = this.receivableBillsWithPlans[orderIndex];
// Update the invoice plans for the specific order
this.$set(currentOrder, 'invoicePlans', [...selectedPlans]);
this.isInvoicePlanSelectorOpen = false;
this.$modal.msgSuccess(`已更新开票计划选择,共 ${selectedPlans.length}`);
},
handleConfirm() {
// Validate main form fields
if (!this.form.invoiceBillType) {
this.$modal.msgError('请选择开票单类型');
return;
}
if (!this.form.invoiceTime) {
this.$modal.msgError('请选择预计开票时间');
return;
}
// Validate each receivable order's invoice plans
for (const order of this.receivableBillsWithPlans) {
if (!order.invoicePlans || order.invoicePlans.length === 0) {
this.$modal.msgError(`应收单 ${order.receivableBillCode} 至少需要一条开票计划`);
return;
}
for (const plan of order.invoicePlans) {
if (!plan.planInvoiceDate) {
this.$modal.msgError(`应收单 ${order.receivableBillCode} 的开票计划中预计开票时间不能为空。`);
return;
}
if (plan.planAmount === null || plan.planAmount === undefined || plan.planAmount <= 0) {
this.$modal.msgError(`应收单 ${order.receivableBillCode} 的开票计划中预计开票金额必须大于0。`);
return;
}
if (plan.planRate === null || plan.planRate === undefined) {
this.$modal.msgError(`应收单 ${order.receivableBillCode} 的开票计划中开票比例不能为空。`);
return;
}
}
}
// Construct the final data to be emitted to the parent
const mergedInvoiceData = {
invoiceBillType: this.form.invoiceBillType,
invoiceTime: this.form.invoiceTime,
// Collect all receivable orders with their updated invoice plans
receivableBills: this.receivableBillsWithPlans.map(order => ({
id: order.id,
receivableBillCode: order.receivableBillCode,
invoicePlans: order.invoicePlans.map(plan => ({
planInvoiceDate: plan.planInvoiceDate,
planAmount: plan.planAmount,
planRate: plan.planRate,
remark: plan.remark,
id: plan.id,
})),
})),
totalMergeInvoiceAmount: this.totalPlannedAmount, // Total amount for the merged bill
};
this.$emit('confirm', mergedInvoiceData);
this.dialogVisible = false;
},
handleCancel() {
this.dialogVisible = false;
this.resetForm();
},
resetForm() {
this.form = {
invoiceBillType: 'FROM_RECEIVABLE',
customerName: '',
invoiceTime: null,
};
this.receivableBillsWithPlans = [];
this.currentReceivableBillIndexForPlan = -1;
this.loadingInvoicePlans = false;
},
handleOpenInvoicePlanSelector(row, index) {
this.planTitle = `选择开票计划 - ${row.receivableBillCode}`;
this.chooseReceivable = row;
this.currentReceivableBillIndexForPlan = index;
this.isInvoicePlanSelectorOpen = true;
console.log(this.chooseReceivable.id)
},
handleInvoicePlanConfirm(updatedPlans) {
// Update the invoice plans for the specific order
if (this.currentReceivableBillIndexForPlan !== -1) {
this.$set(this.receivableBillsWithPlans[this.currentReceivableBillIndexForPlan], 'invoicePlans', updatedPlans);
}
this.isInvoicePlanSelectorOpen = false;
this.currentReceivableBillIndexForPlan = -1;
},
calculateOrderCurrentInvoiceAmount(orderId) {
const order = this.receivableBillsWithPlans.find(o => o.id === orderId);
if (order && order.invoicePlans) {
return order.invoicePlans.reduce((sum, plan) => sum + (plan.planAmount || 0), 0);
}
return 0;
},
calculateOrderCurrentInvoiceRate(orderId) {
const order = this.receivableBillsWithPlans.find(o => o.id === orderId);
if (order && order.invoicePlans && order.uninvoicedAmount >= 0) {
const currentAmount = this.calculateOrderCurrentInvoiceAmount(orderId);
return this.$calc.mul(this.$calc.div(currentAmount ,order.totalPriceWithTax,4 ),100);
}
return 0;
},
},
};
</script>
<style scoped>
.dialog-body {
max-height: 70vh;
overflow-y: auto;
padding-right: 10px; /* To prevent scrollbar from overlapping content */
}
.total-info {
margin-top: 20px;
text-align: right;
font-weight: bold;
}
</style>

View File

@ -0,0 +1,352 @@
<template>
<el-dialog title="合并发起收款单" :visible.sync="dialogVisible" width="80%" @close="handleClose" append-to-body>
<div class="dialog-body">
<el-form ref="form" :model="form" :inline="true" label-width="120px">
<el-row>
<el-col :span="8">
<el-form-item label="收款单类型" prop="receiptBillType">
<el-select disabled v-model="form.receiptBillType" placeholder="请选择收款单类型" clearable>
<el-option
v-for="dict in dict.type.receipt_bill_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="进货商名称">
<el-input v-model="form.partnerName" readonly/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="预计收款时间" prop="estimatedReceiptTime">
<el-date-picker
v-model="form.estimatedReceiptTime"
type="date"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期"
></el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider content-position="left">销售应收单表</el-divider>
<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="planReceiptDate" width="180"/>
<el-table-column label="收款计划" align="center" width="100" prop="planAmount">
</el-table-column>
<!-- <el-table-column label="项目名称" align="center" prop="projectName" width="150"/> -->
<el-table-column label="合同编号" align="center" prop="orderCode" width="150"/>
<el-table-column label="出入库单号" align="center" prop="inventoryCode" width="150"/>
<!-- <el-table-column label="收款状态" align="center" prop="collectionStatus" width="120">
<template slot-scope="scope">
<dict-tag :options="dict.type.collection_status" :value="scope.row.collectionStatus"/>
</template>
</el-table-column> -->
<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" width="120">
<template slot-scope="scope">
{{ calculateOrderCurrentReceiptAmount(scope.row.id).toFixed(2) }}
</template>
</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">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleOpenReceiptPlanSelector(scope.row, scope.$index)"
>选择
</el-button>
</template>
</el-table-column>
</el-table>
<div class="total-info">
<span style="margin-left: 20px;">计划收款总金额: <el-tag type="success">{{
totalPlannedAmount.toFixed(2)
}}</el-tag></span>
<span>计划收款比例: <el-tag type="info">{{ this.$calc.mul(this.$calc.div(totalPlannedAmount,totalReceivableAmountWithTax,4),100) }}%</el-tag></span>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="handleCancel"> </el-button>
<el-button type="primary" @click="handleConfirm"> </el-button>
</div>
<el-dialog :title="planTitle" :visible.sync="isReceiptPlanSelectorOpen" width="70%"
@close="isReceiptPlanSelectorOpen=false" append-to-body>
<receipt-plan-selector
ref="planSelector"
:receivable-data="chooseReceivable"
:selected-plans="chooseReceivable.receiptPlans"
@confirm="handleReceiptPlanConfirm"
/>
<div slot="footer" class="dialog-footer">
<el-button @click="isReceiptPlanSelectorOpen=false"> </el-button>
<!-- <el-button type="primary" @click="handleConfirm" > </el-button>-->
<el-button type="primary" @click="handleChooseConfirm"> </el-button>
</div>
</el-dialog>
<!-- 收款计划选择器弹窗 -->
</el-dialog>
</template>
<script>
import ReceiptPlan from './ReceiptPlan.vue';
export default {
name: "MergeReceiptDialog",
components: {ReceiptPlanSelector: ReceiptPlan},
dicts: ['collection_status','receipt_bill_type'], // Add dicts for dict-tag
props: {
visible: {
type: Boolean,
default: false
},
receivableBills: {
type: Array,
default: () => []
}
},
data() {
return {
internalVisible: this.visible,
planTitle: '',
chooseReceivable: {},
form: {
receiptBillType: 'FROM_RECEIVABLE', // Default to a type
customerName: '',
estimatedReceiptTime: null,
},
receivableBillsWithPlans: [], // Each order will now have its own receiptPlans array
isReceiptPlanSelectorOpen: false,
currentReceivableBillIndexForPlan: -1, // Index of the order in receivableBillsWithPlans
loadingReceiptPlans: false, // Loading state for fetching receipt plans
};
},
computed: {
dialogVisible: {
get() {
return this.internalVisible;
},
set(val) {
this.internalVisible = val;
this.$emit('update:visible', val);
}
},
totalReceivableAmountWithTax() {
return this.receivableBillsWithPlans.reduce((sum, order) => sum + (order.totalPriceWithTax || 0), 0);
},
totalPlannedAmount() {
return this.receivableBillsWithPlans.reduce((orderSum, order) => {
const orderPlansTotal = (order.receiptPlans || []).reduce((planSum, plan) => planSum + (plan.planAmount || 0), 0);
return orderSum + orderPlansTotal;
}, 0);
},
},
watch: {
visible(newVal) {
this.internalVisible = newVal;
if (newVal) {
this.initDialogData();
}
},
receivableBills: {
handler(newVal) {
if (this.dialogVisible) {
this.initDialogData();
}
},
deep: true
}
},
methods: {
initDialogData() {
// Initialize form fields
if (this.receivableBills.length > 0) {
this.form.partnerName = this.receivableBills[0].partnerName;
this.form.estimatedReceiptTime = this.receivableBills[0].estimatedReceiptTime || null; // Use first order's estimated time as default
} else {
this.form.partnerName = '';
this.form.estimatedReceiptTime = null;
}
this.form.receiptBillType = 'FROM_RECEIVABLE'; // Default
// Initialize receivableBillsWithPlans
this.receivableBillsWithPlans = this.receivableBills.map(order => {
const receiptPlans = order.receiptPlans ? [...order.receiptPlans] : [];
if (receiptPlans.length === 0 && order.lastReceiptPlanId) {
receiptPlans.push({
id: order.lastReceiptPlanId,
planAmount: order.planAmount,
planReceiptDate: order.planReceiptDate,
planRate: this.$calc.mul(this.$calc.div(order.planAmount, order.totalPriceWithTax, 4), 100)
});
}
return {
...order,
receiptPlans: receiptPlans, // Retain existing plans if any, otherwise empty
totalPriceWithTax: order.totalPriceWithTax || 0, // Ensure numeric for calculations
unreceivedAmount: order.unreceivedAmount || 0,
receivedAmount: order.receivedAmount || 0, // Ensure numeric for calculations
}
});
},
handleClose() {
this.dialogVisible = false;
this.resetForm();
},
handleChooseConfirm() {
if (!this.$refs.planSelector) {
this.$modal.msgError('无法获取计划选择器组件');
return;
}
const selectedPlans = this.$refs.planSelector.selectedPlan || [];
const orderIndex = this.receivableBillsWithPlans.findIndex(o => o.id === this.chooseReceivable.id);
if (orderIndex === -1) {
this.$modal.msgError('找不到要更新的应收单');
return;
}
const currentOrder = this.receivableBillsWithPlans[orderIndex];
// Update the receipt plans for the specific order
this.$set(currentOrder, 'receiptPlans', [...selectedPlans]);
this.isReceiptPlanSelectorOpen = false;
this.$modal.msgSuccess(`已更新收款计划选择,共 ${selectedPlans.length}`);
},
handleConfirm() {
// Validate main form fields
if (!this.form.receiptBillType) {
this.$modal.msgError('请选择收款单类型');
return;
}
if (!this.form.estimatedReceiptTime) {
this.$modal.msgError('请选择预计收款时间');
return;
}
// Validate each receivable order's receipt plans
for (const order of this.receivableBillsWithPlans) {
if (!order.receiptPlans || order.receiptPlans.length === 0) {
this.$modal.msgError(`应收单 ${order.receivableBillCode} 至少需要一条收款计划`);
return;
}
for (const plan of order.receiptPlans) {
if (!plan.planReceiptDate) {
this.$modal.msgError(`应收单 ${order.receivableBillCode} 的收款计划中预计收款时间不能为空。`);
return;
}
if (plan.planAmount === null || plan.planAmount === undefined || plan.planAmount <= 0) {
this.$modal.msgError(`应收单 ${order.receivableBillCode} 的收款计划中预计收款金额必须大于0。`);
return;
}
if (plan.planRate === null || plan.planRate === undefined) {
this.$modal.msgError(`应收单 ${order.receivableBillCode} 的收款计划中应收比例不能为空。`);
return;
}
}
}
// Construct the final data to be emitted to the parent
const mergedReceiptData = {
receiptBillType: this.form.receiptBillType,
estimatedReceiptTime: this.form.estimatedReceiptTime,
// Collect all receivable orders with their updated receipt plans
receivableBills: this.receivableBillsWithPlans.map(order => ({
id: order.id,
taxRate: order.taxRate,
receivableBillCode: order.receivableBillCode,
receiptPlans: order.receiptPlans.map(plan => ({
planReceiptDate: plan.planReceiptDate,
planAmount: plan.planAmount,
planRate: plan.planRate,
remark: plan.remark,
id: plan.id,
})),
})),
totalMergeReceiptAmount: this.totalPlannedAmount, // Total amount for the merged bill
};
this.$emit('confirm', mergedReceiptData);
this.dialogVisible = false;
},
handleCancel() {
this.dialogVisible = false;
this.resetForm();
},
resetForm() {
this.form = {
receiptBillType: 'FROM_RECEIVABLE',
customerName: '',
estimatedReceiptTime: null,
};
this.receivableBillsWithPlans = [];
this.currentReceivableBillIndexForPlan = -1;
this.loadingReceiptPlans = false;
},
handleOpenReceiptPlanSelector(row, index) {
this.planTitle = `选择收款计划 - ${row.receivableBillCode}`;
this.chooseReceivable = row;
this.currentReceivableBillIndexForPlan = index;
this.isReceiptPlanSelectorOpen = true;
console.log(this.chooseReceivable.id)
},
handleReceiptPlanConfirm(updatedPlans) {
// Update the receipt plans for the specific order
if (this.currentReceivableBillIndexForPlan !== -1) {
this.$set(this.receivableBillsWithPlans[this.currentReceivableBillIndexForPlan], 'receiptPlans', updatedPlans);
}
this.isReceiptPlanSelectorOpen = false;
this.currentReceivableBillIndexForPlan = -1;
},
calculateOrderCurrentReceiptAmount(orderId) {
const order = this.receivableBillsWithPlans.find(o => o.id === orderId);
if (order && order.receiptPlans) {
return order.receiptPlans.reduce((sum, plan) => sum + (plan.planAmount || 0), 0);
}
return 0;
},
calculateOrderCurrentReceiptRate(orderId) {
const order = this.receivableBillsWithPlans.find(o => o.id === orderId);
if (order && order.receiptPlans && order.unreceivedAmount >= 0) {
const currentAmount = this.calculateOrderCurrentReceiptAmount(orderId);
return this.$calc.mul((this.$calc.div(currentAmount ,order.totalPriceWithTax,4 )),100);
}
return 0;
},
},
};
</script>
<style scoped>
.dialog-body {
max-height: 70vh;
overflow-y: auto;
padding-right: 10px; /* To prevent scrollbar from overlapping content */
}
.total-info {
margin-top: 20px;
text-align: right;
font-weight: bold;
}
</style>

View File

@ -0,0 +1,312 @@
<template>
<div class="dialog-body">
<el-divider content-position="left">收款计划</el-divider>
<el-button v-if="isEditing" type="primary" size="mini" @click="handleSaveReceiptPlan"
style="margin-bottom: 10px;">
保存收款计划
</el-button>
<el-button v-if="isEditing" type="primary" size="mini" @click="handleSyncToInvoicePlan"
style="margin-bottom: 10px; margin-left: 10px;">
同步至开票计划
</el-button>
<el-button v-else type="primary" size="mini" @click="isEditing=true"
style="margin-bottom: 10px;">
编辑
</el-button>
<el-table :data="receiptPlans" border @selection-change="selectPlan" ref="receiptPlanTable">
<el-table-column type="selection" width="50" align="center" :selectable="selectableRow"/>
<el-table-column label="序号" type="index" width="50" align="center"></el-table-column>
<el-table-column label="预计收款时间" align="center" width="200">
<template slot-scope="scope">
<el-date-picker v-model="scope.row.planReceiptDate" type="date" style="width: 180px"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期"
:disabled="!isEditing || isNumberStr(scope.row.detailId)"></el-date-picker>
</template>
</el-table-column>
<el-table-column label="预计收款金额" align="center" width="230">
<template slot-scope="scope">
<el-input-number
v-model="scope.row.planAmount"
:precision="2"
:step="100"
:min="0.01"
:readonly="!scope.row.detailId"
:max="totalPriceWithTax"
@change="handleAmountChange(scope.row)"
:disabled="!isEditing || isNumberStr(scope.row.detailId)"
></el-input-number>
</template>
</el-table-column>
<el-table-column label="应收比例(%)" align="center" width="230">
<template slot-scope="scope">
<el-input-number
v-model="scope.row.planRate"
:precision="2"
:step="1"
:min="0.01"
:max="100"
:readonly="!scope.row.detailId"
@change="handleRateChange(scope.row)"
:disabled="!isEditing || isNumberStr(scope.row.detailId)"
></el-input-number>
</template>
</el-table-column>
<el-table-column label="备注" align="center">
<template slot-scope="scope">
<el-input v-model="scope.row.remark" placeholder="请输入备注"
:disabled="!isEditing || isNumberStr(scope.row.detailId)"></el-input>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="150" fixed="right">
<template slot-scope="scope">
<el-button v-if="isEditing && !isNumberStr(scope.row.detailId)"
size="mini"
type="text"
icon="el-icon-plus"
@click="handleAddReceiptPlanRow"
>增加下行
</el-button>
<el-button v-if="isEditing && !isNumberStr(scope.row.detailId)"
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDeleteReceiptPlanRow(scope.$index)"
:disabled="receiptPlans.length === 1 || scope.row.status === 'received'"
>删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- <div class="total-info">-->
<!-- <span>应收单未收款金额: <el-tag type="info">{{ totalUnreceivedAmount.toFixed(2) }}</el-tag></span>-->
<!-- <span style="margin-left: 20px;">计划收款总金额: <el-tag type="success">{{-->
<!-- totalPlannedAmount.toFixed(2)-->
<!-- }}</el-tag></span>-->
<!-- </div>-->
</div>
</template>
<script>
import {getReceiptPlan, updateReceiptPlan, syncToInvoicePlan} from "@/api/finance/receivable";
import {isNumberStr} from "@/utils";
export default {
name: "ReceiptPlanSelector",
props: {
receivableData: {
type: Object,
default: () => {
}
},
isInitEdit: {
type: Boolean,
default: false
},
selectedPlans: {
type: Array,
default: () => []
}
},
data() {
return {
selectedPlan:[],
isEditing: false,
loading: false,
receiptPlans: [],
};
},
computed: {
title() {
return `选择收款计划 - ${this.receivableData.receivableBillCode}`;
},
totalPlannedAmount() {
return this.receiptPlans.reduce((sum, plan) => sum + (plan.planAmount || 0), 0);
},
totalUnreceivedAmount() {
return this.receivableData.unreceivedAmount || 0;
},
totalPriceWithTax() {
return this.receivableData.totalPriceWithTax || 0;
}
},
watch: {
'receivableData.id': {
handler(newVal, oldVal) {
if (newVal) {
this.fetchReceiptPlans(newVal)
}
},
immediate: true
},
isInitEdit: {
handler(newVal) {
if (newVal) {
this.isEditing = newVal
}
},
immediate: true
}
},
methods: {
isNumberStr,
selectableRow(row, index){
return !row.detailId;
},
selectPlan( selection){
this.selectedPlan=selection
},
fetchReceiptPlans(receivableId) {
if (this.receivableData && receivableId) {
getReceiptPlan(receivableId).then(response => {
this.receiptPlans = response.data.map(item => ({
...item,
status: item.status || 'pending'
}));
if (this.receiptPlans.length === 0) {
this.initDefaultReceiptPlan();
} else {
this.$nextTick(() => {
this.receiptPlans.forEach(plan => {
const isSelected = this.selectedPlans.some(selected => selected.id === plan.id);
if (isSelected) {
this.$refs.receiptPlanTable.toggleRowSelection(plan, true);
}
});
});
}
})
} else {
this.initDefaultReceiptPlan();
}
},
initDefaultReceiptPlan() {
this.receiptPlans = [{
planReceiptDate: null,
planAmount: this.totalUnreceivedAmount,
planRate: 100,
remark: '',
status: 'pending'
}];
},
handleSaveReceiptPlan() {
if (!this.validateReceiptPlans()) {
return;
}
if (!this.validateReceiptPlanTotals()) {
return;
}
for (let i = 0; i < this.receiptPlans.length; i++) {
const plan = this.receiptPlans[i];
if (!plan.planReceiptDate) {
this.$modal.msgError(`${i + 1} 行收款计划的预计收款时间不能为空。`);
return;
}
if (plan.planAmount === null || plan.planAmount === undefined || plan.planAmount === '' || plan.planAmount < 0) {
this.$modal.msgError(`${i + 1} 行收款计划的预计收款金额不能为空。`);
return;
}
if (plan.planRate === null || plan.planRate === undefined || plan.planRate === '') {
this.$modal.msgError(`${i + 1} 行收款计划的应收比例不能为空。`);
return;
}
}
updateReceiptPlan(this.receivableData.id, this.receiptPlans).then(() => {
this.$modal.msgSuccess("保存成功");
this.fetchReceiptPlans(this.receivableData.id);
});
},
handleSyncToInvoicePlan() {
this.$modal.confirm('是否确认同步收款计划至开票计划?').then(() => {
return syncToInvoicePlan(this.receivableData.id);
}).then(() => {
this.$emit('syncPlan')
this.$modal.msgSuccess("同步成功");
}).catch(() => {});
},
handleAddReceiptPlanRow() {
this.receiptPlans.push({
planReceiptDate: null,
planAmount: 0,
planRate: 0,
remark: '',
status: 'pending'
});
},
handleDeleteReceiptPlanRow(index) {
if (this.receiptPlans.length === 1) {
this.$modal.msgError("至少需要保留一条收款计划。");
return;
}
if (this.receiptPlans[index].status === 'received') {
this.$modal.msgError("已收款的计划不能删除。");
return;
}
this.receiptPlans.splice(index, 1);
},
handleAmountChange(row) {
if (this.totalPriceWithTax === 0) {
row.planRate = 0;
return;
}
row.planRate = this.$calc.mul((this.$calc.div(row.planAmount, this.totalPriceWithTax,4)), 100);
},
handleRateChange(row) {
row.planAmount = this.$calc.div(this.$calc.mul(this.totalPriceWithTax , row.planRate),100);
},
validateReceiptPlanTotals() {
const totalAmount = this.receiptPlans.reduce((sum, plan) => sum + (plan.planAmount || 0), 0);
if (totalAmount !== this.totalPriceWithTax) {
this.$modal.msgError(`预计收款金额之和应该等于应收总金额[${this.totalPriceWithTax}]`);
return false;
}
return true;
},
validateReceiptPlans() {
if (this.receiptPlans.length === 0) {
this.$modal.msgError("请至少添加一条收款计划。");
return false;
}
for (let i = 0; i < this.receiptPlans.length; i++) {
const plan = this.receiptPlans[i];
if (!plan.planReceiptDate) {
this.$modal.msgError(`${i + 1} 行收款计划的预计收款时间不能为空。`);
return false;
}
if (plan.planAmount === null || plan.planAmount === undefined || plan.planAmount <= 0) {
this.$modal.msgError(`${i + 1} 行收款计划的预计收款金额必须大于0。`);
return false;
}
if (plan.planRate === null || plan.planRate === undefined || plan.planRate === '') {
this.$modal.msgError(`${i + 1} 行收款计划的应收比例不能为空。`);
return false;
}
}
return true;
}
}
};
</script>
<style scoped>
.dialog-body {
max-height: 70vh;
overflow-y: auto;
padding-right: 10px; /* To prevent scrollbar from overlapping content */
}
.total-info {
margin-top: 20px;
text-align: right;
font-weight: bold;
}
</style>

View File

@ -0,0 +1,318 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
<el-form-item label="项目编号" prop="projectCode">
<el-input
v-model="queryParams.projectCode"
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="应收单编号" prop="receivableBillCode">
<el-input
v-model="queryParams.receivableBillCode"
placeholder="请输入应收单编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="客户名称" prop="customerName">
<el-input
v-model="queryParams.customerName"
placeholder="请输入客户名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="产品类型" prop="productType">
<el-select v-model="queryParams.productType" placeholder="请选择产品类型" clearable>
<el-option
v-for="dict in dict.type.product_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="收款状态" prop="collectionStatus">
<el-select v-model="queryParams.collectionStatus" placeholder="请选择收款状态" clearable>
<el-option
v-for="dict in dict.type.collection_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<!-- <el-form-item label="开票状态" prop="invoiceStatus">
<el-select v-model="queryParams.invoiceStatus" placeholder="请选择开票状态" clearable>
<el-option
v-for="dict in dict.type.invoice_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item> -->
<el-form-item label="预计收款时间">
<el-date-picker
v-model="estimatedReceiptDateRange"
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 icon="el-icon-plus" @click="handleMergeAndInitiateReceipt" v-hasPermi="['finance:receivable:mergeReceipt']">
合并并发起收款单
</el-button>
</el-col>
<el-col :span="1.5" >
<el-button type="primary" plain icon="el-icon-plus" @click="handleMergeAndInitiateInvoice" v-hasPermi="['finance:receivable:mergeInvoice']">
合并并发起开票单
</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="receivableList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" />
<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="receivableBillCode" width="150" />
<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="hasAdvanceReceipt" width="150" /> -->
<el-table-column label="进货商名称" align="center" prop="partnerName" width="150" />
<el-table-column label="产品类型" align="center" prop="productType" width="120">
<template slot-scope="scope">
<dict-tag :options="dict.type.product_type" :value="scope.row.productType"/>
</template>
</el-table-column>
<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="uninvoicedAmount" width="120" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160" fixed="right">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['finance:receivable:edit']"
>查看详情</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
v-show="scope.row.unreceivedAmount!==0"
@click="handleGeneratedReceipt(scope.row)"
v-hasPermi="['finance:receivable:edit']"
>生成收款单</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['finance:receivable:remove']"
>删除</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"
/>
<!-- 修改弹窗 -->
<edit-form :visible.sync="open" :data="selectedRow" />
<!-- 合并收款单弹窗 -->
<merge-receipt-dialog :visible.sync="isMergeReceiptDialogOpen" :receivable-bills="selectedReceivableRows" @confirm="confirmMergeReceipt" />
<!-- 合并开票单弹窗 -->
<merge-invoice-dialog :visible.sync="isMergeInvoiceDialogOpen" :receivable-bills="selectedReceivableRows" @confirm="confirmMergeInvoice" />
</div>
</template>
<script>
import { listReceivable, mergeAndInitiateReceipt, mergeAndInitiateInvoice } from "@/api/finance/receivable";
import EditForm from './components/EditForm.vue';
import MergeReceiptDialog from './components/MergeReceiptDialog.vue';
import MergeInvoiceDialog from './components/MergeInvoiceDialog.vue';
export default {
name: "Receivable",
components: { EditForm, MergeReceiptDialog, MergeInvoiceDialog },
dicts: ['product_type', 'collection_status', 'invoice_status'],
data() {
return {
//
open: false,
//
selectedRow: {},
//
loading: true,
//
showSearch: true,
//
total: 0,
//
receivableList: [],
//
dateRange: [],
//
estimatedReceiptDateRange: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
projectCode: null,
projectName: null,
receivableBillCode: null,
customerName: null,
productType: null,
collectionStatus: null,
createTimeStart: null,
createTimeEnd: null,
estimatedReceiptTimeStart: null,
estimatedReceiptTimeEnd: null
},
//
selectedReceivableRows: [],
//
isMergeReceiptDialogOpen: false,
//
isMergeInvoiceDialogOpen: false
};
},
created() {
this.getList();
},
methods: {
/** 查询销售应收单列表 */
getList() {
this.loading = true;
if (null != this.dateRange && '' != this.dateRange) {
this.queryParams.createTimeStart = this.dateRange[0];
this.queryParams.createTimeEnd = this.dateRange[1];
}
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.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = [];
this.estimatedReceiptDateRange = [];
this.resetForm("queryForm");
this.queryParams.createTimeStart=null;
this.queryParams.createTimeEnd=null;
this.queryParams.estimatedReceiptTimeStart=null;
this.queryParams.estimatedReceiptTimeEnd=null;
this.handleQuery();
},
/** 修改按钮操作 */
handleUpdate(row) {
this.selectedRow = row;
this.open = true;
},
/** 删除按钮操作 */
handleDelete(row) {
this.$modal.confirm('是否确认删除销售应收单编号为"' + row.receivableBillCode + '"的数据项?').then(function() {
return Promise.resolve();
}).then(() => {
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 多选框选中数据 */
handleSelectionChange(selection) {
this.selectedReceivableRows = selection;
},
handleGeneratedReceipt(row) {
this.selectedReceivableRows=[row]
this.handleMergeAndInitiateReceipt()
},
/** 合并并发起收款单按钮操作 */
handleMergeAndInitiateReceipt() {
if (this.selectedReceivableRows.length === 0) {
this.$modal.msgWarning("请选择至少一条应收单进行合并操作");
return;
}
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.
if (customerLength > 1) {
this.$modal.msgWarning("请选择同一家客户的应收单进行合并操作");
return;
}
this.isMergeReceiptDialogOpen = true;
},
/** 确认合并收款单操作 */
confirmMergeReceipt(receiptData) {
mergeAndInitiateReceipt(receiptData).then(() => {
this.$modal.msgSuccess("合并收款单发起成功");
this.isMergeReceiptDialogOpen = false;
this.getList(); // Refresh the list
});
},
/** 合并并发起开票单按钮操作 */
handleMergeAndInitiateInvoice() {
if (this.selectedReceivableRows.length === 0) {
this.$modal.msgWarning("请选择至少一条应收单进行合并操作");
return;
}
let customerLength = new Set(this.selectedReceivableRows.map(item=>item.customerCode)).size;
if (customerLength > 1) {
this.$modal.msgWarning("请选择同一家客户的应收单进行合并操作");
return;
}
this.isMergeInvoiceDialogOpen = true;
},
/** 确认合并开票单操作 */
confirmMergeInvoice(invoiceData) {
mergeAndInitiateInvoice(invoiceData).then(() => {
this.$modal.msgSuccess("合并开票单发起成功");
this.isMergeInvoiceDialogOpen = false;
this.getList(); // Refresh the list
});
}
}
};
</script>

View File

@ -0,0 +1,395 @@
<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,120 @@
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.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
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.service.IOmsPayableWriteOffService;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* Controller
*
* @author zghz
* @date 2025-12-16
*/
@RestController
@RequestMapping("/sip/writeOff")
public class OmsPayableWriteOffController extends BaseController
{
@Autowired
private IOmsPayableWriteOffService omsPayableWriteOffService;
/**
*
*/
@RequiresPermissions("sip:writeOff:list")
@GetMapping("/list")
public TableDataInfo list(WriteOffQueryDto writeOffQueryDto)
{
startPage();
List<OmsPayableWriteOff> list = omsPayableWriteOffService.selectOmsPayableWriteOffList(writeOffQueryDto);
return getDataTable(list);
}
/**
*
*/
@RequiresPermissions("sip:writeOff:export")
@Log(title = "采购应付核销单", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, WriteOffQueryDto writeOffQueryDto)
{
List<OmsPayableWriteOff> list = omsPayableWriteOffService.selectOmsPayableWriteOffList(writeOffQueryDto);
ExcelUtil<OmsPayableWriteOff> util = new ExcelUtil<OmsPayableWriteOff>(OmsPayableWriteOff.class);
util.exportExcel(response, list, "采购应付核销单数据");
}
/**
*
*/
@RequiresPermissions("sip:writeOff:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return AjaxResult.success(omsPayableWriteOffService.selectOmsPayableWriteOffById(id));
}
/**
*
*/
@RequiresPermissions("sip:writeOff:add")
@Log(title = "采购应付核销单", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody WriteOffRequestDto writeOffRequestDto)
{
Long writeOffId = omsPayableWriteOffService.insertOmsPayableWriteOff(writeOffRequestDto);
return AjaxResult.success();
}
/**
*
*/
@RequiresPermissions("sip:writeOff:edit")
@Log(title = "采购应付核销单", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody OmsPayableWriteOff omsPayableWriteOff)
{
return toAjax(omsPayableWriteOffService.updateOmsPayableWriteOff(omsPayableWriteOff));
}
/**
*
*/
@RequiresPermissions("sip:writeOff:remove")
@Log(title = "采购应付核销单", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(omsPayableWriteOffService.deleteOmsPayableWriteOffByIds(ids));
}
/**
* ID
*/
@RequiresPermissions("sip:writeOff:query")
@GetMapping("/details/{writeOffId}")
public AjaxResult getWriteOffDetails(@PathVariable("writeOffId") Long writeOffId)
{
List<WriteOffDetailResultDto> details = omsPayableWriteOffService.selectWriteOffDetailsByWriteOffId(writeOffId);
return AjaxResult.success(details);
}
}

View File

@ -0,0 +1,70 @@
package com.ruoyi.sip.controller;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.sip.domain.OmsReceiptBill;
import com.ruoyi.sip.service.IOmsReceiptBillService;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
/**
* @Author ch
* @Desc (OmsReceiptBill)
* @Date 2025-12-16 17:47:25
*/
@RestController
@RequestMapping("omsReceiptBill")
public class OmsReceiptBillController extends BaseController {
@Autowired
private IOmsReceiptBillService omsReceiptBillService;
@GetMapping("/list")
public TableDataInfo list(OmsReceiptBill omsReceiptBill) {
startPage();
List<OmsReceiptBill> list = omsReceiptBillService.queryAll(omsReceiptBill);
return getDataTable(list);
}
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) {
return AjaxResult.success(omsReceiptBillService.queryById(id));
}
@PostMapping("/insert")
public AjaxResult add(@RequestBody OmsReceiptBill omsReceiptBill) {
return toAjax(omsReceiptBillService.insert(omsReceiptBill));
}
@PutMapping("/update")
public AjaxResult edit(@RequestBody OmsReceiptBill omsReceiptBill) {
return toAjax(omsReceiptBillService.update(omsReceiptBill));
}
@DeleteMapping("/{id}")
public AjaxResult remove(@PathVariable("id") Long id) {
return toAjax(omsReceiptBillService.deleteById(id));
}
/**
*
*/
@DeleteMapping("/remove/batch/{ids}")
public AjaxResult batchRemove(@PathVariable("ids") Long[] ids) {
return AjaxResult.success(omsReceiptBillService.batchRemove(ids));
}
}

View File

@ -0,0 +1,134 @@
package com.ruoyi.sip.controller;
import java.util.List;
import com.ruoyi.sip.domain.dto.MergedInvoiceDataDto;
import com.ruoyi.sip.domain.dto.MergedPaymentDataDto;
import com.ruoyi.sip.domain.dto.MergedReceiptDataDto;
import com.ruoyi.sip.domain.dto.MergedReceviableReceiptDataDto;
import com.ruoyi.sip.service.IOmsReceivableReceiptDetailService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.sip.domain.OmsReceivableBill;
import com.ruoyi.sip.service.IOmsReceivableBillService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* Controller
*
* @author ruoyi
* @date 2025-12-16
*/
@Controller
@RequestMapping("/finance/receivable")
public class OmsReceivableBillController extends BaseController
{
private String prefix = "finance/receivable";
@Autowired
private IOmsReceivableBillService omsReceivableBillService;
@RequiresPermissions("finance:receivable:view")
@GetMapping()
public String receivable()
{
return prefix + "/receivable";
}
/**
*
*/
@RequiresPermissions("finance:receivable:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(@RequestBody OmsReceivableBill omsReceivableBill)
{
startPage();
List<OmsReceivableBill> list = omsReceivableBillService.selectOmsReceivableBillList(omsReceivableBill);
return getDataTable(list);
}
/**
*
*/
@RequiresPermissions("finance:receivable:export")
@Log(title = "销售应收单", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(OmsReceivableBill omsReceivableBill)
{
List<OmsReceivableBill> list = omsReceivableBillService.selectOmsReceivableBillList(omsReceivableBill);
ExcelUtil<OmsReceivableBill> util = new ExcelUtil<OmsReceivableBill>(OmsReceivableBill.class);
return util.exportExcel(list, "销售应收单数据");
}
@RequiresPermissions("finance:receivable:query")
@Log(title = "销售应收单", businessType = BusinessType.INSERT)
@GetMapping("/{id}")
@ResponseBody
public AjaxResult query(@PathVariable("id") Long id)
{
return AjaxResult.success(omsReceivableBillService.query(id));
}
/**
*
*/
@RequiresPermissions("finance:receivable:edit")
@Log(title = "销售应收单", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(OmsReceivableBill omsReceivableBill)
{
return toAjax(omsReceivableBillService.updateOmsReceivableBill(omsReceivableBill));
}
/**
*
*/
@RequiresPermissions("finance:receivable:remove")
@Log(title = "销售应收单", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(omsReceivableBillService.deleteOmsReceivableBillByIds(ids));
}
/**
*
*/
@RequiresPermissions("finance:payable:mergePayment")
@Log(title = "合并并发起付款单", businessType = BusinessType.INSERT)
@PostMapping("/mergeAndInitiateReceipt")
@ResponseBody
public AjaxResult mergeAndInitiateReceipt(@RequestBody MergedReceviableReceiptDataDto dto)
{
return toAjax(omsReceivableBillService.mergeAndInitiateReceipt(dto));
}
/**
*
*/
// @RequiresPermissions("inventory:inner:add") // Using permission from button in vue file
// @Log(title = "合并并发起收票单", businessType = BusinessType.INSERT)
// @PostMapping("/mergeAndInitiateReceipt")
// @ResponseBody
// public AjaxResult mergeAndInitiateReceipt(@RequestBody MergedReceiptDataDto dto)
// {
// return toAjax(omsPayableBillService.mergeAndInitiateReceipt(dto));
// }
}

View File

@ -0,0 +1,36 @@
package com.ruoyi.sip.controller;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.sip.domain.OmsReceivableInvoicePlan;
import com.ruoyi.sip.domain.OmsReceivableReceiptPlan;
import com.ruoyi.sip.service.IOmsReceivableInvoicePlanService;
import com.ruoyi.sip.service.IOmsReceivableReceiptPlanService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/finance/receivable/invoice/plan")
public class OmsReceivableInvoicePlanController extends BaseController {
@Autowired
private IOmsReceivableInvoicePlanService invoicePlanService;
@GetMapping(value = "/{receivableBillId}")
public AjaxResult getInfo(@PathVariable("receivableBillId") Long receivableBillId)
{
return AjaxResult.success(invoicePlanService.listByReceivableBillId(receivableBillId));
}
@PostMapping("/{receivableBillId}")
public AjaxResult updateInvoicePlan(@PathVariable("receivableBillId") Long receivableBillId, @RequestBody List<OmsReceivableInvoicePlan> invoicePlanList) {
invoicePlanService.updateInvoicePlans(receivableBillId, invoicePlanList);
return AjaxResult.success();
}
}

View File

@ -0,0 +1,43 @@
package com.ruoyi.sip.controller;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.sip.domain.OmsReceivableReceiptPlan;
import com.ruoyi.sip.domain.OmsReceivableInvoicePlan;
import com.ruoyi.sip.service.IOmsReceivableReceiptPlanService;
import com.ruoyi.sip.service.IOmsReceivableInvoicePlanService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/finance/receivable/plan")
public class OmsReceivablePlanController extends BaseController {
@Autowired
private IOmsReceivableReceiptPlanService receiptPlanService;
@Autowired
private IOmsReceivableInvoicePlanService invoicePlanService;
@GetMapping("/{receivableBillId}")
public AjaxResult getReceiptPlan(@PathVariable("receivableBillId") Long receivableBillId) {
return AjaxResult.success(receiptPlanService.selectOmsReceivableReceiptPlanListByReceivableBillId(receivableBillId));
}
@PostMapping("/{receivableBillId}")
public AjaxResult updateReceiptPlan(@PathVariable("receivableBillId") Long receivableBillId, @RequestBody List<OmsReceivableReceiptPlan> receiptPlanList) {
receiptPlanService.updateReceiptPlans(receivableBillId, receiptPlanList);
return AjaxResult.success();
}
@PostMapping("/sync/{receivableBillId}")
public AjaxResult syncReceiptToInvoicePlan(@PathVariable("receivableBillId") Long receivableBillId) {
receiptPlanService.syncReceiptToInvoicePlan(receivableBillId);
return AjaxResult.success();
}
}

View File

@ -58,6 +58,8 @@ public class OmsFinAttachment extends BaseEntity
/** 付款单 */ /** 付款单 */
PAYMENT("payment", "付款单"), PAYMENT("payment", "付款单"),
INVOICE("ticket", "收票单"), INVOICE("ticket", "收票单"),
RECEIPT("receipt", "应收-收款单"),
// INVOICE("ticket", "收票单"),

View File

@ -0,0 +1,76 @@
package com.ruoyi.sip.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* oms_payable_write_off
*
* @author zghz
* @date 2025-12-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class OmsPayableWriteOff extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 核销单编号 */
@Excel(name = "核销单编号")
private String writeOffCode;
/** 核销类型 AUTO:系统自动核销 USER:用户手动核销 */
@Excel(name = "核销类型")
private String writeOffType;
/** 付款单编号 */
@Excel(name = "付款单编号")
private String paymentBillCode;
/** 供应商编码 */
@Excel(name = "供应商编码")
private String vendorCode;
/** 本次核销总金额 */
@Excel(name = "本次核销总金额")
private BigDecimal writeOffAmount = BigDecimal.ZERO;
/** 本次核销未税总金额 */
@Excel(name = "本次核销未税总金额")
private BigDecimal writeOffAmountWithoutTax = BigDecimal.ZERO;
/** 本次核销税额 */
@Excel(name = "本次核销税额")
private BigDecimal writeOffTaxAmount = BigDecimal.ZERO;
/** 核销时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "核销时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date writeOffTime;
/** 备注 */
@Excel(name = "备注")
private String remark;
/** 创建人 */
private String createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** 更新人 */
private String updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}

View File

@ -0,0 +1,75 @@
package com.ruoyi.sip.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* oms_payable_write_off_detail
*
* @author zghz
* @date 2025-12-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class OmsPayableWriteOffDetail extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 核销单ID */
private Long writeOffId;
/** 应付单ID */
private Long payableBillId;
/** 应付单编号 */
@Excel(name = "应付单编号")
private String payableBillCode;
/** 应付单付款计划ID */
private Long paymentPlanId;
/** 付款单ID */
private Long paymentBillId;
/** 付款单编号 */
@Excel(name = "付款单编号")
private String paymentBillCode;
/** 核销金额 */
@Excel(name = "核销金额")
private BigDecimal writeOffAmount = BigDecimal.ZERO;
/** 本次核销未税总金额 */
@Excel(name = "本次核销未税总金额")
private BigDecimal writeOffAmountWithoutTax = BigDecimal.ZERO;
/** 本次核销税额 */
@Excel(name = "本次核销税额")
private BigDecimal writeOffTaxAmount = BigDecimal.ZERO;
/** 备注 */
@Excel(name = "备注")
private String remark;
/** 创建人 */
private String createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** 更新人 */
private String updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}

View File

@ -0,0 +1,197 @@
package com.ruoyi.sip.domain;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
import lombok.Getter;
/**
* (OmsReceiptBill)
*
* @author ch
* @since 2025-12-16 17:47:26
*/
@Data
public class OmsReceiptBill {
/**
* ID
*/
private Long id;
/**
*
*/
private String receiptBillCode;
/**
* (FROM_RECEIVABLE, PRE_RECEIPT)
*/
private String receiptBillType;
/**
*
*/
private Date receiptTime;
/**
*
*/
private Date actualReceiptTime;
/**
*
*/
private String partnerCode;
private String partnerName;
/**
*
*/
private String orderCode;
/**
*
*/
private BigDecimal totalPriceWithTax;
/**
*
*/
private BigDecimal totalPriceWithoutTax;
/**
*
*/
private BigDecimal taxAmount;
/**
*
*/
private String createBy;
/**
*
*/
private Date createTime;
/**
*
*/
private String updateBy;
/**
*
*/
private Date updateTime;
/**
*
*/
private String remark;
/**
* 0 2
*/
private String delFlag;
/**
*
*/
private String projectCode;
/**
*
*/
private String projectName;
/**
*
*/
private String receiptStatus;
/**
*
*/
private String approveStatus;
/**
*
*/
private String approveNode;
/**
*
*/
private Date approveTime;
/**
*
*/
private String receiptMethod;
/**
*
*/
private String receiptAccountName;
/**
*
*/
private String receiptBankNumber;
/**
*
*/
private String receiptBankOpenAddress;
/**
*
*/
private String bankNumber;
/**
* 退 0:退 1:退
*/
private String refundStatus;
@Getter
public enum ReceiptBillTypeEnum {
/** 应付单生成 */
FROM_RECEIVABLE("FROM_RECEIVABLE", "应付单生成"),
/** 预付单 */
PRE_RECEIPT("PRE_RECEIPT", "预付单"),
/** 退款单 */
REFUND("REFUND", "退款单"),
;
private final String code;
private final String desc;
ReceiptBillTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
}
@Getter
public enum ReceiptStatusEnum {
/** 应付单生成 */
REFUNDED("-1", "已退款"),
WAIT_PAYMENT("1", "未付款"),
/** 预付单 */
PAYMENT("2", "已付款"),
;
private final String code;
private final String desc;
ReceiptStatusEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
}
}

View File

@ -0,0 +1,97 @@
package com.ruoyi.sip.domain;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
/**
* oms_receivable_bill
*
* @author ruoyi
* @date 2025-12-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class OmsReceivableBill extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
private List<Long> idList;
/** 应收单编号 */
@Excel(name = "应收单编号")
private String receivableBillCode;
/** 最新收款计划ID */
private Long lastReceiptPlanId;
/** 最新开票计划ID */
private Long lastInvoicePlanId;
/** 客户编码 */
@Excel(name = "客户编码")
private String partnerCode;
private String partnerName;
/** 合同编号 */
@Excel(name = "合同编号")
private String orderCode;
/** 出库/入库单号 */
@Excel(name = "出库/入库单号")
private String inventoryCode;
/** 产品类型 */
@Excel(name = "产品类型")
private String productType;
private String productCode;
/** 含税总价 */
@Excel(name = "含税总价")
private BigDecimal totalPriceWithTax;
/** 未税总价 */
@Excel(name = "未税总价")
private BigDecimal totalPriceWithoutTax;
/** 税率 */
@Excel(name = "税率")
private BigDecimal taxRate;
/** 税额 */
@Excel(name = "税额")
private BigDecimal taxAmount;
/** 已收款金额 */
@Excel(name = "已收款金额")
private BigDecimal receivedAmount;
/** 未收款金额 */
@Excel(name = "未收款金额")
private BigDecimal unreceivedAmount;
private BigDecimal planAmount;
private Date planReceiptDate;
/** 已开票金额 */
@Excel(name = "已开票金额")
private BigDecimal invoicedAmount;
/** 未开票金额 */
@Excel(name = "未开票金额")
private BigDecimal uninvoicedAmount;
private String projectName;
private String projectCode;
private List<OmsReceivableReceiptDetail> detailList;
}

View File

@ -0,0 +1,80 @@
package com.ruoyi.sip.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import java.math.BigDecimal;
import java.util.Date;
/**
* oms_receivable_invoice_detail
*
* @author ruoyi
* @date 2025-12-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class OmsReceivableInvoiceDetail extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键 */
private Long id;
/** 开票计划ID */
@Excel(name = "开票计划ID")
private Long invoicePlanId;
/** 应收单ID */
@Excel(name = "应收单ID")
private Long receivableBillId;
/** 实际开票时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "实际开票时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date invoiceTime;
/** 开票金额 */
@Excel(name = "开票金额")
private BigDecimal invoiceAmount;
/** 开票比例 */
@Excel(name = "开票比例")
private BigDecimal invoiceRate;
/** 发票编号 */
@Excel(name = "发票编号")
private String invoiceBillCode;
/** 备注 */
@Excel(name = "备注")
private String remark;
/** 1:正常开票 3:红冲 */
@Excel(name = "开票明细类型")
private String receivableDetailType;
private String invoiceStatus;
@Getter
public enum ReceivableDetailTypeEnum {
/** 正常开票 */
NORMAL_INVOICE("1", "正常开票"),
/** 红冲 */
REFUND("3", "红冲"),
;
private final String code;
private final String desc;
ReceivableDetailTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
}
}

View File

@ -0,0 +1,49 @@
package com.ruoyi.sip.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* oms_receivable_invoice_plan
*
* @author ruoyi
* @date 2025-12-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class OmsReceivableInvoicePlan extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键 */
private Long id;
/** 应收单ID */
@Excel(name = "应收单ID")
private Long receivableBillId;
/** 计划开票时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "计划开票时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date planInvoiceDate;
/** 计划开票金额 */
@Excel(name = "计划开票金额")
private BigDecimal planAmount;
/** 计划开票比例 */
@Excel(name = "计划开票比例")
private BigDecimal planRate;
/** 备注 */
@Excel(name = "备注")
private String remark;
private Long detailId;
}

View File

@ -0,0 +1,86 @@
package com.ruoyi.sip.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* oms_receivable_receipt_detail
*
* @author ruoyi
* @date 2025-12-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class OmsReceivableReceiptDetail extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键 */
private Long id;
private List<Long> idList;
/** 收款计划ID */
@Excel(name = "收款计划ID")
private Long receiptPlanId;
/** 应收单ID */
@Excel(name = "应收单ID")
private Long receivableBillId;
/** 实际收款时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "实际收款时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date receiptTime;
/** 收款金额 */
@Excel(name = "收款金额")
private BigDecimal receiptAmount;
/** 收款比例 */
@Excel(name = "收款比例")
private BigDecimal receiptRate;
/** 收款单号 */
@Excel(name = "收款单号")
private String receiptBillCode;
private Long receiptBillId;
/** 备注 */
@Excel(name = "备注")
private String remark;
/** 1:正常收款 2:预收核销 3:退款 */
@Excel(name = "收款明细类型")
private String receivableDetailType;
/** 回执单附件ID */
private OmsFinAttachment finAttachment;
private Date actualReceiptTime;
private String receiptStatus;
@Getter
public enum ReceivableDetailTypeEnum {
/** 正常收款 */
NORMAL_RECEIPT("1", "正常收款"),
/** 预收核销 */
PRE_RECEIVE_WRITE_OFF("2", "预收核销"),
REFUND("3", "退款"),
;
private final String code;
private final String desc;
ReceivableDetailTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
}
}

View File

@ -0,0 +1,49 @@
package com.ruoyi.sip.domain;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* oms_receivable_receipt_plan
*
* @author ruoyi
* @date 2025-12-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class OmsReceivableReceiptPlan extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键 */
private Long id;
/** 应收单ID */
@Excel(name = "应收单ID")
private Long receivableBillId;
/** 计划收款日期 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "计划收款日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date planReceiptDate;
/** 计划收款金额 */
@Excel(name = "计划收款金额")
private BigDecimal planAmount;
/** 计划收款比例 */
@Excel(name = "计划收款比例")
private BigDecimal planRate;
/** 备注 */
@Excel(name = "备注")
private String remark;
private Long detailId;
}

View File

@ -0,0 +1,16 @@
package com.ruoyi.sip.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Data
public class MergedInvoiceDataDto {
private String invoiceBillType;
private Date invoiceTime;
private Date customerInvoiceTime;
private List<ReceivableOrderReceiptDto> receivableOrders;
private BigDecimal totalMergeInvoiceAmount;
}

View File

@ -0,0 +1,15 @@
package com.ruoyi.sip.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Data
public class MergedReceviableReceiptDataDto {
private String receiptBillType;
private Date estimatedReceiptTime;
private List<ReceivableOrderReceiptDto> receivableBills;
private BigDecimal totalMergeReceiptAmount;
}

View File

@ -0,0 +1,16 @@
package com.ruoyi.sip.domain.dto;
import com.ruoyi.sip.domain.OmsReceivableInvoicePlan;
import com.ruoyi.sip.domain.OmsReceivableReceiptPlan;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class ReceivableOrderReceiptDto {
private Long id;
private String receivableBillCode;
private BigDecimal taxRate;
private List<OmsReceivableReceiptPlan> receiptPlans;
}

View File

@ -0,0 +1,159 @@
package com.ruoyi.sip.dto;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* DTO
*
* @author zghz
* @date 2025-12-16
*/
public class WriteOffDetailResultDto
{
/** 主键ID */
private Long id;
/** 核销单ID */
private Long writeOffId;
/** 核销单号 */
private String writeOffCode;
/** 应付单ID */
private Long payableBillId;
/** 应付单编号 */
private String payableBillCode;
/** 应付单付款计划ID */
private Long paymentPlanId;
/** 付款单ID */
private Long paymentBillId;
/** 付款单编号 */
private String paymentBillCode;
/** 核销金额 */
private BigDecimal writeOffAmount;
/** 本次核销未税总金额 */
private BigDecimal writeOffAmountWithoutTax;
/** 本次核销税额 */
private BigDecimal writeOffTaxAmount;
/** 备注 */
private String remark;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getWriteOffId() {
return writeOffId;
}
public void setWriteOffId(Long writeOffId) {
this.writeOffId = writeOffId;
}
public String getWriteOffCode() {
return writeOffCode;
}
public void setWriteOffCode(String writeOffCode) {
this.writeOffCode = writeOffCode;
}
public Long getPayableBillId() {
return payableBillId;
}
public void setPayableBillId(Long payableBillId) {
this.payableBillId = payableBillId;
}
public String getPayableBillCode() {
return payableBillCode;
}
public void setPayableBillCode(String payableBillCode) {
this.payableBillCode = payableBillCode;
}
public Long getPaymentPlanId() {
return paymentPlanId;
}
public void setPaymentPlanId(Long paymentPlanId) {
this.paymentPlanId = paymentPlanId;
}
public Long getPaymentBillId() {
return paymentBillId;
}
public void setPaymentBillId(Long paymentBillId) {
this.paymentBillId = paymentBillId;
}
public String getPaymentBillCode() {
return paymentBillCode;
}
public void setPaymentBillCode(String paymentBillCode) {
this.paymentBillCode = paymentBillCode;
}
public BigDecimal getWriteOffAmount() {
return writeOffAmount;
}
public void setWriteOffAmount(BigDecimal writeOffAmount) {
this.writeOffAmount = writeOffAmount;
}
public BigDecimal getWriteOffAmountWithoutTax() {
return writeOffAmountWithoutTax;
}
public void setWriteOffAmountWithoutTax(BigDecimal writeOffAmountWithoutTax) {
this.writeOffAmountWithoutTax = writeOffAmountWithoutTax;
}
public BigDecimal getWriteOffTaxAmount() {
return writeOffTaxAmount;
}
public void setWriteOffTaxAmount(BigDecimal writeOffTaxAmount) {
this.writeOffTaxAmount = writeOffTaxAmount;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}

View File

@ -0,0 +1,57 @@
package com.ruoyi.sip.dto;
import lombok.Data;
import java.math.BigDecimal;
import javax.validation.constraints.NotNull;
/**
* DTO
*
* @author zghz
* @date 2025-12-16
*/
@Data
public class WriteOffItemDto
{
/**
* ID
*/
@NotNull(message = "应付单ID不能为空")
private Long payableBillId;
/**
* ID
*/
@NotNull(message = "应付单付款计划ID不能为空")
private Long paymentPlanId;
/**
* ID
*/
@NotNull(message = "付款单ID不能为空")
private Long paymentBillId;
/**
*
*/
@NotNull(message = "核销金额不能为空")
private BigDecimal writeOffAmount;
/**
*
*/
private BigDecimal writeOffAmountWithoutTax;
/**
*
*/
private BigDecimal writeOffTaxAmount;
/**
*
*/
private String remark;
}

View File

@ -0,0 +1,38 @@
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

@ -0,0 +1,40 @@
package com.ruoyi.sip.dto;
import lombok.Data;
import java.util.List;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* DTO
*
* @author zghz
* @date 2025-12-16
*/
@Data
public class WriteOffRequestDto
{
/**
* ID
*/
@NotNull(message = "付款单ID不能为空")
private Long paymentBillId;
/**
*
*/
private List<WriteOffItemDto> writeOffItems;
/**
*
*/
@NotBlank(message = "供应商代码不能为空")
private String vendorCode;
/**
*
*/
private String remark;
}

View File

@ -0,0 +1,85 @@
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

@ -0,0 +1,61 @@
package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.OmsPayableWriteOff;
/**
* Mapper
*
* @author zghz
* @date 2025-12-16
*/
public interface OmsPayableWriteOffMapper
{
/**
*
*
* @param id ID
* @return
*/
public OmsPayableWriteOff selectOmsPayableWriteOffById(Long id);
/**
*
*
* @param omsPayableWriteOff
* @return
*/
public List<OmsPayableWriteOff> selectOmsPayableWriteOffList(OmsPayableWriteOff omsPayableWriteOff);
/**
*
*
* @param omsPayableWriteOff
* @return
*/
public int insertOmsPayableWriteOff(OmsPayableWriteOff omsPayableWriteOff);
/**
*
*
* @param omsPayableWriteOff
* @return
*/
public int updateOmsPayableWriteOff(OmsPayableWriteOff omsPayableWriteOff);
/**
*
*
* @param id ID
* @return
*/
public int deleteOmsPayableWriteOffById(Long id);
/**
*
*
* @param ids ID
* @return
*/
public int deleteOmsPayableWriteOffByIds(Long[] ids);
}

View File

@ -0,0 +1,51 @@
package com.ruoyi.sip.mapper;
import com.ruoyi.sip.domain.OmsReceiptBill;
import java.util.List;
/**
* @Author ch
* @Desc (OmsReceiptBill)访
* @Date 2025-12-16 17:47:26
*/
public interface OmsReceiptBillMapper {
/**
*
*
* @param omsReceiptBill
* @return
*/
List<OmsReceiptBill> queryAll(OmsReceiptBill omsReceiptBill);
/**
* ID
*/
OmsReceiptBill queryById(Long id);
/**
*
*/
int insert(OmsReceiptBill omsReceiptBill);
/**
*
*/
int update(OmsReceiptBill omsReceiptBill);
/**
*
*/
int deleteById(Long id);
/**
* id
*/
int batchRemove(Long[] ids);
int selectMaxCodeByPrefix(String codePrefix);
}

View File

@ -0,0 +1,79 @@
package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.OmsReceivableBill;
/**
* Mapper
*
* @author ruoyi
* @date 2025-12-16
*/
public interface OmsReceivableBillMapper
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableBill selectOmsReceivableBillById(Long id);
/**
*
*
* @param omsReceivableBill
* @return
*/
public List<OmsReceivableBill> selectOmsReceivableBillList(OmsReceivableBill omsReceivableBill);
/**
*
*
* @param omsReceivableBill
* @return
*/
public int insertOmsReceivableBill(OmsReceivableBill omsReceivableBill);
/**
*
*
* @param omsReceivableBill
* @return
*/
public int updateOmsReceivableBill(OmsReceivableBill omsReceivableBill);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableBillById(Long id);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableBillByIds(String ids);
/**
*
*
* @param codePrefix
* @return
*/
Integer selectMaxCodeByPrefix(String codePrefix);
/**
*
*
* @param receivableBills
* @return
*/
int updateBatchReceivableBillInvoiceInfo(List<OmsReceivableBill> receivableBills);
int updateBatchReceivableBillReceiptInfo(List<OmsReceivableBill> receivableBills);
}

View File

@ -0,0 +1,73 @@
package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
import com.ruoyi.sip.domain.OmsReceivableInvoiceDetail;
/**
* Mapper
*
* @author ruoyi
* @date 2025-12-16
*/
public interface OmsReceivableInvoiceDetailMapper
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableInvoiceDetail selectOmsReceivableInvoiceDetailById(Long id);
/**
*
*
* @param omsReceivableInvoiceDetail
* @return
*/
public List<OmsReceivableInvoiceDetail> selectOmsReceivableInvoiceDetailList(OmsReceivableInvoiceDetail omsReceivableInvoiceDetail);
/**
*
*
* @param omsReceivableInvoiceDetail
* @return
*/
public int insertOmsReceivableInvoiceDetail(OmsReceivableInvoiceDetail omsReceivableInvoiceDetail);
/**
*
*
* @param omsReceivableInvoiceDetail
* @return
*/
public int updateOmsReceivableInvoiceDetail(OmsReceivableInvoiceDetail omsReceivableInvoiceDetail);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableInvoiceDetailById(Long id);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableInvoiceDetailByIds(String ids);
List<OmsReceivableInvoiceDetail> listByReceivableBillIdList(List<Long> collect);
/**
* ID
*
* @param invoicePlanIds ID
* @return
*/
List<OmsReceivableInvoiceDetail> selectByInvoicePlanIds(List<Long> invoicePlanIds);
}

View File

@ -0,0 +1,64 @@
package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.OmsReceivableInvoicePlan;
/**
* Mapper
*
* @author ruoyi
* @date 2025-12-16
*/
public interface OmsReceivableInvoicePlanMapper
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableInvoicePlan selectOmsReceivableInvoicePlanById(Long id);
/**
*
*
* @param omsReceivableInvoicePlan
* @return
*/
public List<OmsReceivableInvoicePlan> selectOmsReceivableInvoicePlanList(OmsReceivableInvoicePlan omsReceivableInvoicePlan);
/**
*
*
* @param omsReceivableInvoicePlan
* @return
*/
public int insertOmsReceivableInvoicePlan(OmsReceivableInvoicePlan omsReceivableInvoicePlan);
/**
*
*
* @param omsReceivableInvoicePlan
* @return
*/
public int updateOmsReceivableInvoicePlan(OmsReceivableInvoicePlan omsReceivableInvoicePlan);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableInvoicePlanById(Long id);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableInvoicePlanByIds(String ids);
OmsReceivableInvoicePlan firstUnPayPlan(Long receivableBillId);
}

View File

@ -0,0 +1,65 @@
package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.OmsReceivableReceiptDetail;
/**
* Mapper
*
* @author ruoyi
* @date 2025-12-16
*/
public interface OmsReceivableReceiptDetailMapper
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableReceiptDetail selectOmsReceivableReceiptDetailById(Long id);
/**
*
*
* @param omsReceivableReceiptDetail
* @return
*/
public List<OmsReceivableReceiptDetail> selectOmsReceivableReceiptDetailList(OmsReceivableReceiptDetail omsReceivableReceiptDetail);
/**
*
*
* @param omsReceivableReceiptDetail
* @return
*/
public int insertOmsReceivableReceiptDetail(OmsReceivableReceiptDetail omsReceivableReceiptDetail);
/**
*
*
* @param omsReceivableReceiptDetail
* @return
*/
public int updateOmsReceivableReceiptDetail(OmsReceivableReceiptDetail omsReceivableReceiptDetail);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableReceiptDetailById(Long id);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableReceiptDetailByIds(String ids);
List<OmsReceivableReceiptDetail> list(OmsReceivableReceiptDetail omsReceivableReceiptDetail);
List<OmsReceivableReceiptDetail> selectByPaymentPlanIds(List<Long> allReceiptPlanIds);
}

View File

@ -0,0 +1,79 @@
package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.OmsReceivableReceiptPlan;
/**
* Mapper
*
* @author ruoyi
* @date 2025-12-16
*/
public interface OmsReceivableReceiptPlanMapper
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableReceiptPlan selectOmsReceivableReceiptPlanById(Long id);
/**
*
*
* @param omsReceivableReceiptPlan
* @return
*/
public List<OmsReceivableReceiptPlan> selectOmsReceivableReceiptPlanList(OmsReceivableReceiptPlan omsReceivableReceiptPlan);
/**
* ID
*
* @param receivableBillId ID
* @return
*/
public List<OmsReceivableReceiptPlan> selectOmsReceivableReceiptPlanListByReceivableBillId(Long receivableBillId);
/**
*
*
* @param omsReceivableReceiptPlan
* @return
*/
public int insertOmsReceivableReceiptPlan(OmsReceivableReceiptPlan omsReceivableReceiptPlan);
/**
*
*
* @param omsReceivableReceiptPlan
* @return
*/
public int updateOmsReceivableReceiptPlan(OmsReceivableReceiptPlan omsReceivableReceiptPlan);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableReceiptPlanById(Long id);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableReceiptPlanByIds(String ids);
/**
* ID
*
* @param receivableBillId ID
* @return
*/
public int deleteByReceivableBillId(Long receivableBillId);
OmsReceivableReceiptPlan firstUnPayPlan(Long id);
}

View File

@ -0,0 +1,72 @@
package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsPayableWriteOff;
import com.ruoyi.sip.dto.WriteOffRequestDto;
import com.ruoyi.sip.dto.WriteOffQueryDto;
import com.ruoyi.sip.dto.WriteOffDetailResultDto;
/**
* Service
*
* @author zghz
* @date 2025-12-16
*/
public interface IOmsPayableWriteOffService
{
/**
*
*
* @param id ID
* @return
*/
public OmsPayableWriteOff selectOmsPayableWriteOffById(Long id);
/**
*
*
* @param writeOffQueryDto
* @return
*/
public List<OmsPayableWriteOff> selectOmsPayableWriteOffList(WriteOffQueryDto writeOffQueryDto);
/**
*
*
* @param writeOffRequestDto
* @return
*/
public Long insertOmsPayableWriteOff(WriteOffRequestDto writeOffRequestDto);
/**
*
*
* @param omsPayableWriteOff
* @return
*/
public int updateOmsPayableWriteOff(OmsPayableWriteOff omsPayableWriteOff);
/**
*
*
* @param ids ID
* @return
*/
public int deleteOmsPayableWriteOffByIds(Long[] ids);
/**
*
*
* @param id ID
* @return
*/
public int deleteOmsPayableWriteOffById(Long id);
/**
* ID
*
* @param writeOffId ID
* @return
*/
public List<WriteOffDetailResultDto> selectWriteOffDetailsByWriteOffId(Long writeOffId);
}

View File

@ -0,0 +1,48 @@
package com.ruoyi.sip.service;
import com.ruoyi.sip.domain.OmsReceiptBill;
import java.util.List;
/**
* @Author ch
* @Desc (OmsReceiptBill)
* @Date 2025-12-16 17:47:26
*/
public interface IOmsReceiptBillService {
/**
*
*/
List<OmsReceiptBill> queryAll(OmsReceiptBill omsReceiptBill);
/**
* ID
*/
OmsReceiptBill queryById(Long id);
/**
*
*/
int insert(OmsReceiptBill omsReceiptBill);
/**
*
*/
int update(OmsReceiptBill omsReceiptBill);
/**
*
*/
int deleteById(Long id);
/**
* id
*/
int batchRemove(Long[] ids);
}

View File

@ -0,0 +1,76 @@
package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsReceivableBill;
import com.ruoyi.sip.domain.dto.MergedInvoiceDataDto;
import com.ruoyi.sip.domain.dto.MergedReceviableReceiptDataDto;
/**
* Service
*
* @author ruoyi
* @date 2025-12-16
*/
public interface IOmsReceivableBillService
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableBill selectOmsReceivableBillById(Long id);
/**
*
*
* @param omsReceivableBill
* @return
*/
public List<OmsReceivableBill> selectOmsReceivableBillList(OmsReceivableBill omsReceivableBill);
/**
*
*
* @param omsReceivableBill
* @return
*/
public int insertOmsReceivableBill(OmsReceivableBill omsReceivableBill);
/**
*
*
* @param omsReceivableBill
* @return
*/
public int updateOmsReceivableBill(OmsReceivableBill omsReceivableBill);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableBillByIds(String ids);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableBillById(Long id);
/**
*
*
* @param id
* @return
*/
public OmsReceivableBill query(Long id);
int mergeAndInitiateReceipt(MergedReceviableReceiptDataDto dto);
public int updateReceiptAmount(List<Long> idList);
public int updateInvoiceAmount(List<Long> idList);
}

View File

@ -0,0 +1,73 @@
package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
import com.ruoyi.sip.domain.OmsReceivableInvoiceDetail;
/**
* Service
*
* @author ruoyi
* @date 2025-12-16
*/
public interface IOmsReceivableInvoiceDetailService
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableInvoiceDetail selectOmsReceivableInvoiceDetailById(Long id);
/**
*
*
* @param omsReceivableInvoiceDetail
* @return
*/
public List<OmsReceivableInvoiceDetail> selectOmsReceivableInvoiceDetailList(OmsReceivableInvoiceDetail omsReceivableInvoiceDetail);
/**
*
*
* @param omsReceivableInvoiceDetail
* @return
*/
public int insertOmsReceivableInvoiceDetail(OmsReceivableInvoiceDetail omsReceivableInvoiceDetail);
/**
*
*
* @param omsReceivableInvoiceDetail
* @return
*/
public int updateOmsReceivableInvoiceDetail(OmsReceivableInvoiceDetail omsReceivableInvoiceDetail);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableInvoiceDetailByIds(String ids);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableInvoiceDetailById(Long id);
List<OmsReceivableInvoiceDetail> listByReceivableBillIdList(List<Long> collect);
/**
* ID
*
* @param invoicePlanIds ID
* @return
*/
List<OmsReceivableInvoiceDetail> selectByInvoicePlanIds(List<Long> invoicePlanIds);
}

View File

@ -0,0 +1,68 @@
package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsReceivableInvoicePlan;
import com.ruoyi.sip.domain.OmsReceivableReceiptPlan;
/**
* Service
*
* @author ruoyi
* @date 2025-12-16
*/
public interface IOmsReceivableInvoicePlanService
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableInvoicePlan selectOmsReceivableInvoicePlanById(Long id);
/**
*
*
* @param omsReceivableInvoicePlan
* @return
*/
public List<OmsReceivableInvoicePlan> selectOmsReceivableInvoicePlanList(OmsReceivableInvoicePlan omsReceivableInvoicePlan);
/**
*
*
* @param omsReceivableInvoicePlan
* @return
*/
public int insertOmsReceivableInvoicePlan(OmsReceivableInvoicePlan omsReceivableInvoicePlan);
/**
*
*
* @param omsReceivableInvoicePlan
* @return
*/
public int updateOmsReceivableInvoicePlan(OmsReceivableInvoicePlan omsReceivableInvoicePlan);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableInvoicePlanByIds(String ids);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableInvoicePlanById(Long id);
List<OmsReceivableInvoicePlan> listByReceivableBillId(Long receivableBillId);
void updateInvoicePlans(Long receivableBillId, List<OmsReceivableInvoicePlan> invoicePlanList);
}

View File

@ -0,0 +1,69 @@
package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
import com.ruoyi.sip.domain.OmsReceivableReceiptDetail;
/**
* Service
*
* @author ruoyi
* @date 2025-12-16
*/
public interface IOmsReceivableReceiptDetailService
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableReceiptDetail selectOmsReceivableReceiptDetailById(Long id);
/**
*
*
* @param omsReceivableReceiptDetail
* @return
*/
public List<OmsReceivableReceiptDetail> selectOmsReceivableReceiptDetailList(OmsReceivableReceiptDetail omsReceivableReceiptDetail);
/**
*
*
* @param omsReceivableReceiptDetail
* @return
*/
public int insertOmsReceivableReceiptDetail(OmsReceivableReceiptDetail omsReceivableReceiptDetail);
/**
*
*
* @param omsReceivableReceiptDetail
* @return
*/
public int updateOmsReceivableReceiptDetail(OmsReceivableReceiptDetail omsReceivableReceiptDetail);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableReceiptDetailByIds(String ids);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableReceiptDetailById(Long id);
List<OmsReceivableReceiptDetail> listByReceivableBillId(Long id);
List<OmsReceivableReceiptDetail> selectReceiptPlanByIds(List<Long> allReceiptPlanIds);
List<OmsReceivableReceiptDetail> listByReceivableBillIdList(List<Long> idList);
}

View File

@ -0,0 +1,90 @@
package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsPayablePaymentPlan;
import com.ruoyi.sip.domain.OmsReceivableReceiptPlan;
/**
* Service
*
* @author ruoyi
* @date 2025-12-16
*/
public interface IOmsReceivableReceiptPlanService
{
/**
*
*
* @param id
* @return
*/
public OmsReceivableReceiptPlan selectOmsReceivableReceiptPlanById(Long id);
/**
*
*
* @param omsReceivableReceiptPlan
* @return
*/
public List<OmsReceivableReceiptPlan> selectOmsReceivableReceiptPlanList(OmsReceivableReceiptPlan omsReceivableReceiptPlan);
/**
* ID
*
* @param receivableBillId ID
* @return
*/
public List<OmsReceivableReceiptPlan> selectOmsReceivableReceiptPlanListByReceivableBillId(Long receivableBillId);
/**
*
*
* @param omsReceivableReceiptPlan
* @return
*/
public int insertOmsReceivableReceiptPlan(OmsReceivableReceiptPlan omsReceivableReceiptPlan);
/**
*
*
* @param omsReceivableReceiptPlan
* @return
*/
public int updateOmsReceivableReceiptPlan(OmsReceivableReceiptPlan omsReceivableReceiptPlan);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsReceivableReceiptPlanByIds(String ids);
/**
*
*
* @param id
* @return
*/
public int deleteOmsReceivableReceiptPlanById(Long id);
/**
*
*
* @param receivableBillId ID
* @param receiptPlanList
* @return
*/
public void updateReceiptPlans(Long receivableBillId, List<OmsReceivableReceiptPlan> receiptPlanList);
/**
*
*
* @param receivableBillId ID
* @return
*/
public void syncReceiptToInvoicePlan(Long receivableBillId);
OmsReceivableReceiptPlan firstUnPayPlan(Long id);
}

View File

@ -0,0 +1,239 @@
package com.ruoyi.sip.service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
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
*
* @author zghz
* @date 2025-12-16
*/
@Service
public class OmsPayableWriteOffServiceImpl implements IOmsPayableWriteOffService
{
@Autowired
private OmsPayableWriteOffMapper omsPayableWriteOffMapper;
@Autowired
private OmsPayableWriteOffDetailMapper omsPayableWriteOffDetailMapper;
@Autowired
private OmsPayableBillMapper omsPayableBillMapper;
@Autowired
private OmsPaymentBillMapper omsPaymentBillMapper;
/**
*
*
* @param id ID
* @return
*/
@Override
public OmsPayableWriteOff selectOmsPayableWriteOffById(Long id)
{
return omsPayableWriteOffMapper.selectOmsPayableWriteOffById(id);
}
/**
*
*
* @param writeOffQueryDto
* @return
*/
@Override
public List<OmsPayableWriteOff> selectOmsPayableWriteOffList(WriteOffQueryDto writeOffQueryDto)
{
OmsPayableWriteOff omsPayableWriteOff = new OmsPayableWriteOff();
omsPayableWriteOff.setWriteOffCode(writeOffQueryDto.getWriteOffCode());
omsPayableWriteOff.setVendorCode(writeOffQueryDto.getVendorCode());
return omsPayableWriteOffMapper.selectOmsPayableWriteOffList(omsPayableWriteOff);
}
/**
*
*
* @param writeOffRequestDto
* @return
*/
@Override
@Transactional
public Long insertOmsPayableWriteOff(WriteOffRequestDto writeOffRequestDto)
{
// 获取付款单信息
OmsPaymentBill paymentBill = omsPaymentBillMapper.selectOmsPaymentBillById(writeOffRequestDto.getPaymentBillId());
if (paymentBill == null) {
throw new RuntimeException("付款单不存在");
}
// 创建核销主记录
OmsPayableWriteOff writeOff = new OmsPayableWriteOff();
writeOff.setWriteOffCode(WriteOffCodeGenerator.generateWriteOffCode());
// 默认为用户手动核销
writeOff.setWriteOffType("USER");
writeOff.setPaymentBillCode(paymentBill.getPaymentBillCode());
writeOff.setVendorCode(writeOffRequestDto.getVendorCode());
writeOff.setWriteOffTime(new Date());
writeOff.setRemark(writeOffRequestDto.getRemark());
// 计算总金额和相关税额
BigDecimal totalAmount = BigDecimal.ZERO;
BigDecimal totalAmountWithoutTax = BigDecimal.ZERO;
BigDecimal totalTaxAmount = BigDecimal.ZERO;
for (WriteOffItemDto item : writeOffRequestDto.getWriteOffItems()) {
totalAmount = totalAmount.add(item.getWriteOffAmount());
totalAmountWithoutTax = totalAmountWithoutTax.add(item.getWriteOffAmountWithoutTax());
totalTaxAmount = totalTaxAmount.add(item.getWriteOffTaxAmount());
}
writeOff.setWriteOffAmount(totalAmount);
writeOff.setWriteOffAmountWithoutTax(totalAmountWithoutTax);
writeOff.setWriteOffTaxAmount(totalTaxAmount);
// 设置创建时间
writeOff.setCreateTime(new Date());
writeOff.setUpdateTime(new Date());
// 保存核销主记录
omsPayableWriteOffMapper.insertOmsPayableWriteOff(writeOff);
// 保存核销明细
for (WriteOffItemDto item : writeOffRequestDto.getWriteOffItems())
{
OmsPayableWriteOffDetail detail = new OmsPayableWriteOffDetail();
detail.setWriteOffId(writeOff.getId());
detail.setPayableBillId(item.getPayableBillId());
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());
}
// 设置付款单编号
detail.setPaymentBillCode(paymentBill.getPaymentBillCode());
// 保存核销明细记录
omsPayableWriteOffDetailMapper.insertOmsPayableWriteOffDetail(detail);
}
return writeOff.getId();
}
/**
*
*
* @param omsPayableWriteOff
* @return
*/
@Override
public int updateOmsPayableWriteOff(OmsPayableWriteOff omsPayableWriteOff)
{
return omsPayableWriteOffMapper.updateOmsPayableWriteOff(omsPayableWriteOff);
}
/**
*
*
* @param ids ID
* @return
*/
@Override
@Transactional
public int deleteOmsPayableWriteOffByIds(Long[] ids)
{
// 先删除明细记录
omsPayableWriteOffDetailMapper.deleteOmsPayableWriteOffDetailByWriteOffIds(ids);
// 再删除主记录
return omsPayableWriteOffMapper.deleteOmsPayableWriteOffByIds(ids);
}
/**
*
*
* @param id ID
* @return
*/
@Override
@Transactional
public int deleteOmsPayableWriteOffById(Long id)
{
// 先删除明细记录
omsPayableWriteOffDetailMapper.deleteOmsPayableWriteOffDetailByWriteOffId(id);
// 再删除主记录
return omsPayableWriteOffMapper.deleteOmsPayableWriteOffById(id);
}
/**
* ID
*
* @param writeOffId ID
* @return
*/
@Override
public List<WriteOffDetailResultDto> selectWriteOffDetailsByWriteOffId(Long writeOffId)
{
List<OmsPayableWriteOffDetail> details = omsPayableWriteOffDetailMapper.selectOmsPayableWriteOffDetailByWriteOffId(writeOffId);
return details.stream().map(this::convertToWriteOffDetailResultDto).collect(Collectors.toList());
}
/**
* OmsPayableWriteOffDetailWriteOffDetailResultDto
*
* @param detail
* @return DTO
*/
private WriteOffDetailResultDto convertToWriteOffDetailResultDto(OmsPayableWriteOffDetail detail) {
WriteOffDetailResultDto dto = new WriteOffDetailResultDto();
dto.setId(detail.getId());
dto.setWriteOffId(detail.getWriteOffId());
// 从核销主表获取核销单号
OmsPayableWriteOff writeOff = omsPayableWriteOffMapper.selectOmsPayableWriteOffById(detail.getWriteOffId());
if (writeOff != null) {
dto.setWriteOffCode(writeOff.getWriteOffCode());
}
dto.setPayableBillId(detail.getPayableBillId());
dto.setPayableBillCode(detail.getPayableBillCode());
dto.setPaymentPlanId(detail.getPaymentPlanId());
dto.setPaymentBillId(detail.getPaymentBillId());
dto.setPaymentBillCode(detail.getPaymentBillCode());
dto.setWriteOffAmount(detail.getWriteOffAmount());
dto.setWriteOffAmountWithoutTax(detail.getWriteOffAmountWithoutTax());
dto.setWriteOffTaxAmount(detail.getWriteOffTaxAmount());
dto.setRemark(detail.getRemark());
dto.setCreateTime(detail.getCreateTime());
return dto;
}
}

View File

@ -60,6 +60,8 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
private IOmsInventoryDeliveryDetailService deliveryDetailService; private IOmsInventoryDeliveryDetailService deliveryDetailService;
@Autowired @Autowired
private IOmsPayableBillService payableBillService; private IOmsPayableBillService payableBillService;
@Autowired
private IOmsReceivableBillService billService;
@Value("${oms.inventory.innerTax:0.13}") @Value("${oms.inventory.innerTax:0.13}")
private String defaultTax; private String defaultTax;
@ -268,6 +270,31 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
List<InventoryInfo> saveList = inventoryInfos.stream().peek(item -> item.setPayableBillCode(payableBill.getPayableBillCode())).collect(Collectors.toList()); List<InventoryInfo> saveList = inventoryInfos.stream().peek(item -> item.setPayableBillCode(payableBill.getPayableBillCode())).collect(Collectors.toList());
inventoryInfoService.saveBatch(saveList); inventoryInfoService.saveBatch(saveList);
} }
//生成应收单
OmsReceivableBill receivableBill = new OmsReceivableBill();
receivableBill.setProductCode(inventoryOuter.getProductCode());
receivableBill.setProductType(productInfo.getType());
ProjectOrderInfo orderInfo = projectOrderInfoService.selectProjectOrderInfoByOrderCode(inventoryDelivery.getOrderCode());
receivableBill.setPartnerCode(orderInfo.getPartnerCode());
receivableBill.setPartnerName(orderInfo.getPartnerName());
receivableBill.setOrderCode(orderInfo.getOrderCode());
receivableBill.setInventoryCode(inventoryDelivery.getOuterCode());
List<ProjectProductInfo> collect = projectProductInfos.stream().filter(item -> item.getProductBomCode().equals(inventoryOuter.getProductCode())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(collect)) {
ProjectProductInfo projectProductInfo = collect.get(0);
BigDecimal price = projectProductInfo.getPrice();
InventoryDelivery inventoryDelivery1 = selectInventoryDeliveryById(inventoryDelivery.getId());
BigDecimal allPrice = price.multiply(new BigDecimal(inventoryDelivery1.getQuantity().toString()));
receivableBill.setTotalPriceWithTax(allPrice);
BigDecimal defaultTaxRate = projectProductInfo.getTaxRate()==null?new BigDecimal(defaultTax):projectProductInfo.getTaxRate().divide(new BigDecimal("100"));
BigDecimal allPriceWithOutTax = allPrice.divide(BigDecimal.ONE.add(defaultTaxRate), 2, RoundingMode.HALF_UP);
receivableBill.setTaxRate(defaultTaxRate);
receivableBill.setTotalPriceWithoutTax(allPriceWithOutTax);
receivableBill.setTaxAmount(allPrice.subtract(receivableBill.getTotalPriceWithoutTax()));
receivableBill.setUninvoicedAmount(allPrice);
receivableBill.setUnreceivedAmount(allPrice);
billService.insertOmsReceivableBill(receivableBill);
}
} }

View File

@ -279,7 +279,7 @@ public class OmsPayableBillServiceImpl implements IOmsPayableBillService {
detail.setPaymentRate(paymentPlanDto.getPlanRate()); detail.setPaymentRate(paymentPlanDto.getPlanRate());
detail.setPaymentTime(paymentPlanDto.getPlanPaymentDate()); detail.setPaymentTime(paymentPlanDto.getPlanPaymentDate());
detail.setRemark(paymentPlanDto.getRemark()); detail.setRemark(paymentPlanDto.getRemark());
detail.setCreateBy(ShiroUtils.getLoginName()); detail.setCreateBy(ShiroUtils.getUserId().toString());
detail.setPayableDetailType(OmsPayablePaymentDetail.PayableDetailTypeEnum.APPLY_PAYMENT.getCode()); detail.setPayableDetailType(OmsPayablePaymentDetail.PayableDetailTypeEnum.APPLY_PAYMENT.getCode());
omsPayablePaymentDetailService.insertOmsPayablePaymentDetail(detail); omsPayablePaymentDetailService.insertOmsPayablePaymentDetail(detail);
} }

View File

@ -0,0 +1,93 @@
package com.ruoyi.sip.service.impl;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.enums.ApproveStatusEnum;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.sip.domain.OmsPaymentBill;
import com.ruoyi.sip.domain.OmsReceiptBill;
import com.ruoyi.sip.mapper.OmsReceiptBillMapper;
import com.ruoyi.sip.service.IOmsReceiptBillService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @Author ch
* @Desc (OmsReceiptBill)
* @Date 2025-12-16 17:47:26
*/
@Service
public class OmsReceiptBillServiceImpl implements IOmsReceiptBillService {
@Resource
private OmsReceiptBillMapper omsReceiptBillMapper;
/**
*
*
* @param omsReceiptBill
* @return
*/
@Override
public List<OmsReceiptBill> queryAll(OmsReceiptBill omsReceiptBill) {
List<OmsReceiptBill> dataList = omsReceiptBillMapper.queryAll(omsReceiptBill);
return dataList;
}
@Override
public OmsReceiptBill queryById(Long id) {
return omsReceiptBillMapper.queryById(id);
}
@Override
public int insert(OmsReceiptBill omsReceiptBill) {
omsReceiptBill.setCreateTime(DateUtils.getNowDate());
omsReceiptBill.setCreateBy(ShiroUtils.getUserId().toString());
omsReceiptBill.setReceiptBillCode(generateReceiptBillCode());
omsReceiptBill.setReceiptStatus(OmsReceiptBill.ReceiptStatusEnum.WAIT_PAYMENT.getCode());
omsReceiptBill.setApproveStatus(ApproveStatusEnum.WAIT_COMMIT.getCode());
return omsReceiptBillMapper.insert(omsReceiptBill);
}
private String generateReceiptBillCode() {
String prefix = "SK";
// 查询当天已有的最大序列号
String codePrefix = prefix + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_PATTERN);
int maxSequence = omsReceiptBillMapper.selectMaxCodeByPrefix(codePrefix);
// 生成新的序列号
int newSequence = maxSequence + 1;
// 序列号补零到4位
String sequenceStr = String.format("%04d", newSequence);
return codePrefix + sequenceStr;
}
@Override
public int update(OmsReceiptBill omsReceiptBill) {
return omsReceiptBillMapper.update(omsReceiptBill);
}
@Override
public int deleteById(Long id) {
return omsReceiptBillMapper.deleteById(id);
}
/**
* id
*/
@Override
public int batchRemove(Long[] ids) {
return omsReceiptBillMapper.batchRemove(ids);
}
}

View File

@ -0,0 +1,381 @@
package com.ruoyi.sip.service.impl;
import java.math.BigDecimal;
import java.util.List;
import java.util.Comparator;
import java.util.Map;
import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.domain.dto.MergedInvoiceDataDto;
import com.ruoyi.sip.domain.dto.MergedReceviableReceiptDataDto;
import com.ruoyi.sip.domain.dto.ReceivableOrderReceiptDto;
import com.ruoyi.sip.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.sip.mapper.OmsReceivableBillMapper;
/**
* Service
*
* @author ruoyi
* @date 2025-12-16
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
{
@Autowired
private OmsReceivableBillMapper omsReceivableBillMapper;
@Autowired
private IOmsReceiptBillService receiptBillService;
@Autowired
private IOmsReceivableReceiptDetailService detailService;
@Autowired
private IOmsReceivableReceiptPlanService receiptPlanService;
@Autowired
private IOmsReceivableReceiptDetailService receiptDetailService;
@Autowired
private IOmsReceivableInvoicePlanService invoicePlanService;
@Autowired
private IOmsReceivableInvoiceDetailService invoiceDetailService;
@Value("${oms.inventory.innerTax:0.13}")
private String defaultTax;
/**
*
*
* @param id
* @return
*/
@Override
public OmsReceivableBill selectOmsReceivableBillById(Long id)
{
return omsReceivableBillMapper.selectOmsReceivableBillById(id);
}
/**
*
*
* @param omsReceivableBill
* @return
*/
@Override
public List<OmsReceivableBill> selectOmsReceivableBillList(OmsReceivableBill omsReceivableBill)
{
return omsReceivableBillMapper.selectOmsReceivableBillList(omsReceivableBill);
}
/**
*
*
* @param omsReceivableBill
* @return
*/
@Override
public int updateOmsReceivableBill(OmsReceivableBill omsReceivableBill)
{
return omsReceivableBillMapper.updateOmsReceivableBill(omsReceivableBill);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteOmsReceivableBillByIds(String ids)
{
return omsReceivableBillMapper.deleteOmsReceivableBillByIds(ids);
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteOmsReceivableBillById(Long id)
{
return omsReceivableBillMapper.deleteOmsReceivableBillById(id);
}
/**
*
*
* @param id
* @return
*/
@Override
public OmsReceivableBill query(Long id) {
OmsReceivableBill omsReceivableBill = omsReceivableBillMapper.selectOmsReceivableBillById(id);
List<OmsReceivableReceiptDetail> detailList = detailService.listByReceivableBillId(id);
omsReceivableBill.setDetailList(detailList);
return omsReceivableBill;
}
@Override
@Transactional
public int mergeAndInitiateReceipt(MergedReceviableReceiptDataDto dto) {
// 1. Calculate Tax Totals
BigDecimal totalWithoutTax = BigDecimal.ZERO;
if (CollUtil.isEmpty(dto.getReceivableBills())) {
return 0;
}
// Fetch bills once
for (ReceivableOrderReceiptDto order : dto.getReceivableBills()) {
for (OmsReceivableReceiptPlan plan : order.getReceiptPlans()) {
// 计算每个 plan 的未税金额 = planAmount / (1 + 税率),保留两位小数
BigDecimal taxRate = order.getTaxRate();
if (taxRate == null || taxRate.compareTo(BigDecimal.ZERO) < 0) {
// 如果税率为空或小于0则默认为0.13
taxRate = new BigDecimal(defaultTax);
}
// 计算未税金额 = planAmount / (1 + 税率)
BigDecimal divisor = BigDecimal.ONE.add(taxRate);
BigDecimal planWithoutTax = plan.getPlanAmount().divide(divisor, 2, java.math.RoundingMode.HALF_UP);
totalWithoutTax = totalWithoutTax.add(planWithoutTax);
}
}
// 2. 创建收款单
OmsReceiptBill receiptBill = new OmsReceiptBill();
OmsReceivableBill firstReceivableBill = omsReceivableBillMapper.selectOmsReceivableBillById(dto.getReceivableBills().get(0).getId());
receiptBill.setReceiptBillType(OmsReceiptBill.ReceiptBillTypeEnum.FROM_RECEIVABLE.getCode());
receiptBill.setPartnerCode(firstReceivableBill.getPartnerCode());
receiptBill.setPartnerName(firstReceivableBill.getPartnerName());
receiptBill.setReceiptTime(dto.getEstimatedReceiptTime());
receiptBill.setTotalPriceWithTax(dto.getTotalMergeReceiptAmount());
receiptBill.setTotalPriceWithoutTax(totalWithoutTax);
receiptBill.setTaxAmount(dto.getTotalMergeReceiptAmount().subtract(totalWithoutTax));
receiptBillService.insert(receiptBill);
// 3. 创建收款单 - 防止重复
// 收集所有收款计划ID
List<Long> allReceiptPlanIds = dto.getReceivableBills().stream()
.flatMap(order -> order.getReceiptPlans().stream())
.map(OmsReceivableReceiptPlan::getId)
.collect(java.util.stream.Collectors.toList());
// 查询现有的收款明细记录
java.util.Map<Long, OmsReceivableReceiptDetail> existingDetailsMap = new java.util.HashMap<>();
if (!allReceiptPlanIds.isEmpty()) {
List<OmsReceivableReceiptDetail> existingDetails = receiptDetailService.selectReceiptPlanByIds(allReceiptPlanIds);
// 使用stream将查询结果转化为Map以planId为keydetail为value取createtime最新的数据
existingDetailsMap = existingDetails.stream()
.collect(java.util.stream.Collectors.toMap(
OmsReceivableReceiptDetail::getReceiptPlanId,
detail -> detail,
// 如果有重复数据取createtime最新的数据
(existing, replacement) -> existing.getCreateTime().compareTo(replacement.getCreateTime()) >= 0 ? existing : replacement
));
}
// 遍历所有计划并检查是否有已开票的记录
for (ReceivableOrderReceiptDto receivableOrderDto : dto.getReceivableBills()) {
for (OmsReceivableReceiptPlan plan : receivableOrderDto.getReceiptPlans()) {
// 检查是否存在已开票的记录
OmsReceivableReceiptDetail existingDetail = existingDetailsMap.get(plan.getId());
if (existingDetail != null) {
// 检查是否是已开票状态,如果是则抛出异常
if (!OmsReceivableInvoiceDetail.ReceivableDetailTypeEnum.REFUND.getCode().equals(existingDetail.getReceivableDetailType())) {
throw new ServiceException("计划ID为 " + plan.getId() + " 的开票已处理,请刷新页面后重试");
}
}
OmsReceivableReceiptDetail detail = new OmsReceivableReceiptDetail();
detail.setReceivableBillId(receivableOrderDto.getId());
detail.setReceiptPlanId(plan.getId());
// 生成发票编号
detail.setReceiptBillCode(receiptBill.getReceiptBillCode());
detail.setReceiptAmount(plan.getPlanAmount());
detail.setReceiptRate(plan.getPlanRate());
detail.setReceiptTime(plan.getPlanReceiptDate());
detail.setRemark(plan.getRemark());
detail.setCreateBy(ShiroUtils.getUserId().toString());
detail.setReceivableDetailType(OmsReceivableReceiptDetail.ReceivableDetailTypeEnum.NORMAL_RECEIPT.getCode());
detailService.insertOmsReceivableReceiptDetail(detail);
}
}
// 批量更新应收单的开票相关信息
return SpringUtils.getAopProxy(this).updateReceiptAmount(dto.getReceivableBills().stream().map(ReceivableOrderReceiptDto::getId).collect(java.util.stream.Collectors.toList()));
}
/**
*
*
* @param idList ID
* @return
*/
@Override
public int updateInvoiceAmount(List<Long> idList) {
if (CollUtil.isEmpty(idList)) {
return 0;
}
OmsReceivableBill billCriteria = new OmsReceivableBill();
billCriteria.setIdList(idList);
List<OmsReceivableBill> bills = omsReceivableBillMapper.selectOmsReceivableBillList(billCriteria);
if (CollUtil.isEmpty(bills)) {
return 0;
}
List<OmsReceivableInvoiceDetail> invoiceDetails = invoiceDetailService.listByReceivableBillIdList(idList);
java.util.Map<Long, java.util.Map<String, BigDecimal>> planMap = invoiceDetails.stream()
.collect(java.util.stream.Collectors.groupingBy(
OmsReceivableInvoiceDetail::getReceivableBillId,
java.util.stream.Collectors.groupingBy(
item -> item.getReceivableDetailType() == null ? OmsReceivableInvoiceDetail.ReceivableDetailTypeEnum.NORMAL_INVOICE.getCode() : item.getReceivableDetailType(),
java.util.stream.Collectors.reducing(
BigDecimal.ZERO,
detail -> (detail.getInvoiceAmount() != null) ? detail.getInvoiceAmount() : BigDecimal.ZERO,
BigDecimal::add
))));
for (OmsReceivableBill bill : bills) {
java.util.Map<String, BigDecimal> amountMap = planMap.get(bill.getId());
if (CollUtil.isNotEmpty(amountMap)) {
// 已开票金额 = 正常开票金额 - 红冲金额
BigDecimal invoicedAmount = amountMap.getOrDefault(OmsReceivableInvoiceDetail.ReceivableDetailTypeEnum.NORMAL_INVOICE.getCode(), BigDecimal.ZERO)
.subtract(amountMap.getOrDefault(OmsReceivableInvoiceDetail.ReceivableDetailTypeEnum.REFUND.getCode(), BigDecimal.ZERO));
bill.setInvoicedAmount(invoicedAmount);
// 未开票金额 = 总金额 - 已开票金额
bill.setUninvoicedAmount(bill.getTotalPriceWithTax().subtract(invoicedAmount));
}
// 获取最新未开票计划
OmsReceivableInvoicePlan lastInvoicePlan = invoicePlanService.selectOmsReceivableInvoicePlanList(new OmsReceivableInvoicePlan() {{
setReceivableBillId(bill.getId());
}}).stream()
.filter(p -> p.getDetailId() == null) // 查找未执行的开票计划
.min(java.util.Comparator.comparing(OmsReceivableInvoicePlan::getPlanInvoiceDate))
.orElse(null);
bill.setLastInvoicePlanId(lastInvoicePlan == null ? -1L : lastInvoicePlan.getId());
}
return omsReceivableBillMapper.updateBatchReceivableBillInvoiceInfo(bills);
}
@Override
public int updateReceiptAmount(List<Long> idList) {
if (CollUtil.isEmpty(idList)) {
return 0;
}
OmsReceivableBill receivableBill = new OmsReceivableBill();
receivableBill.setIdList(idList);
List<OmsReceivableBill> receivableBills = omsReceivableBillMapper.selectOmsReceivableBillList(receivableBill);
if (CollUtil.isEmpty(receivableBills)) {
return 0;
}
List<OmsReceivableReceiptDetail> omsReceivableReceiptDetailList = detailService.listByReceivableBillIdList(idList);
Map<Long, Map<String, BigDecimal>> planMap = omsReceivableReceiptDetailList.stream().collect(Collectors.groupingBy(OmsReceivableReceiptDetail::getReceivableBillId,
Collectors.groupingBy(
item -> item.getReceiptStatus() == null ? OmsReceiptBill.ReceiptStatusEnum.WAIT_PAYMENT.getCode() : item.getReceiptStatus(),
Collectors.reducing(
BigDecimal.ZERO,
detail -> (detail.getReceiptAmount()!=null) ? detail.getReceiptAmount() : BigDecimal.ZERO,
BigDecimal::add
))));
for (OmsReceivableBill bill : receivableBills) {
Map<String, BigDecimal> amountMap = planMap.get(bill.getId());
if (CollUtil.isNotEmpty(amountMap)) {
//已付金额 = 已付款金额-退款金额
bill.setReceivedAmount(amountMap.getOrDefault(OmsReceiptBill.ReceiptStatusEnum.PAYMENT.getCode(), BigDecimal.ZERO)
.subtract(amountMap.getOrDefault(OmsReceiptBill.ReceiptStatusEnum.REFUNDED.getCode(), BigDecimal.ZERO)));
//未付金额=总金额-已付金额-付款中金额
bill.setUnreceivedAmount(bill.getTotalPriceWithTax().subtract(bill.getReceivedAmount())
.subtract(amountMap.getOrDefault(OmsReceiptBill.ReceiptStatusEnum.WAIT_PAYMENT.getCode(), BigDecimal.ZERO)));
}
OmsReceivableReceiptPlan lastReceiptPlan = receiptPlanService.firstUnPayPlan(bill.getId());
bill.setLastReceiptPlanId(lastReceiptPlan == null ? -1 : lastReceiptPlan.getId());
}
return omsReceivableBillMapper.updateBatchReceivableBillReceiptInfo(receivableBills);
}
/**
*
*
* @param omsReceivableBill
* @return
*/
@Override
@Transactional
public int insertOmsReceivableBill(OmsReceivableBill omsReceivableBill) {
// 设置初始金额
omsReceivableBill.setUnreceivedAmount(omsReceivableBill.getTotalPriceWithTax());
omsReceivableBill.setUninvoicedAmount(omsReceivableBill.getTotalPriceWithTax());
omsReceivableBill.setReceivedAmount(BigDecimal.ZERO);
omsReceivableBill.setInvoicedAmount(BigDecimal.ZERO);
// 生成应收单编号
omsReceivableBill.setReceivableBillCode(generateReceivableBillCode());
omsReceivableBill.setCreateTime(DateUtils.getNowDate());
omsReceivableBill.setCreateBy(ShiroUtils.getUserId().toString());
int rows = omsReceivableBillMapper.insertOmsReceivableBill(omsReceivableBill);
// 创建默认收款计划
if (rows > 0) {
OmsReceivableReceiptPlan defaultReceiptPlan = new OmsReceivableReceiptPlan();
defaultReceiptPlan.setReceivableBillId(omsReceivableBill.getId());
defaultReceiptPlan.setPlanReceiptDate(DateUtils.getNowDate()); // 默认为当前日期
defaultReceiptPlan.setPlanAmount(omsReceivableBill.getTotalPriceWithTax());
defaultReceiptPlan.setPlanRate(new java.math.BigDecimal("100"));
defaultReceiptPlan.setRemark("默认收款计划");
defaultReceiptPlan.setCreateBy(ShiroUtils.getUserId().toString());
receiptPlanService.insertOmsReceivableReceiptPlan(defaultReceiptPlan);
omsReceivableBill.setLastReceiptPlanId(defaultReceiptPlan.getId());
// 创建默认开票计划
OmsReceivableInvoicePlan defaultInvoicePlan = new OmsReceivableInvoicePlan();
defaultInvoicePlan.setReceivableBillId(omsReceivableBill.getId());
defaultInvoicePlan.setPlanInvoiceDate(DateUtils.getNowDate()); // 默认为当前日期
defaultInvoicePlan.setPlanAmount(omsReceivableBill.getTotalPriceWithTax());
defaultInvoicePlan.setPlanRate(new java.math.BigDecimal("100"));
defaultInvoicePlan.setRemark("默认开票计划");
defaultInvoicePlan.setCreateBy(ShiroUtils.getUserId().toString());
defaultInvoicePlan.setCreateTime(DateUtils.getNowDate());
invoicePlanService.insertOmsReceivableInvoicePlan(defaultInvoicePlan);
omsReceivableBill.setLastInvoicePlanId(defaultInvoicePlan.getId());
updateOmsReceivableBill(omsReceivableBill);
}
return rows;
}
/**
* SKY+YYMMdd+
* @return
*/
private String generateReceivableBillCode() {
String prefix = "SKY";
// 查询当天已有的最大序列号
String codePrefix = prefix + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_PATTERN);
int maxSequence = omsReceivableBillMapper.selectMaxCodeByPrefix(codePrefix);
// 生成新的序列号
int newSequence = maxSequence + 1;
// 序列号补零到4位
String sequenceStr = String.format("%04d", newSequence);
return codePrefix + sequenceStr;
}
}

View File

@ -0,0 +1,109 @@
package com.ruoyi.sip.service.impl;
import java.util.Collections;
import java.util.List;
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.sip.mapper.OmsReceivableInvoiceDetailMapper;
import com.ruoyi.sip.domain.OmsReceivableInvoiceDetail;
import com.ruoyi.sip.service.IOmsReceivableInvoiceDetailService;
/**
* Service
*
* @author ruoyi
* @date 2025-12-16
*/
@Service
public class OmsReceivableInvoiceDetailServiceImpl implements IOmsReceivableInvoiceDetailService
{
@Autowired
private OmsReceivableInvoiceDetailMapper omsReceivableInvoiceDetailMapper;
/**
*
*
* @param id
* @return
*/
@Override
public OmsReceivableInvoiceDetail selectOmsReceivableInvoiceDetailById(Long id)
{
return omsReceivableInvoiceDetailMapper.selectOmsReceivableInvoiceDetailById(id);
}
/**
*
*
* @param omsReceivableInvoiceDetail
* @return
*/
@Override
public List<OmsReceivableInvoiceDetail> selectOmsReceivableInvoiceDetailList(OmsReceivableInvoiceDetail omsReceivableInvoiceDetail)
{
return omsReceivableInvoiceDetailMapper.selectOmsReceivableInvoiceDetailList(omsReceivableInvoiceDetail);
}
/**
*
*
* @param omsReceivableInvoiceDetail
* @return
*/
@Override
public int insertOmsReceivableInvoiceDetail(OmsReceivableInvoiceDetail omsReceivableInvoiceDetail)
{
return omsReceivableInvoiceDetailMapper.insertOmsReceivableInvoiceDetail(omsReceivableInvoiceDetail);
}
/**
*
*
* @param omsReceivableInvoiceDetail
* @return
*/
@Override
public int updateOmsReceivableInvoiceDetail(OmsReceivableInvoiceDetail omsReceivableInvoiceDetail)
{
return omsReceivableInvoiceDetailMapper.updateOmsReceivableInvoiceDetail(omsReceivableInvoiceDetail);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteOmsReceivableInvoiceDetailByIds(String ids)
{
return omsReceivableInvoiceDetailMapper.deleteOmsReceivableInvoiceDetailByIds(ids);
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteOmsReceivableInvoiceDetailById(Long id)
{
return omsReceivableInvoiceDetailMapper.deleteOmsReceivableInvoiceDetailById(id);
}
@Override
public List<OmsReceivableInvoiceDetail> listByReceivableBillIdList(List<Long> collect) {
return omsReceivableInvoiceDetailMapper.listByReceivableBillIdList(collect);
}
@Override
public List<OmsReceivableInvoiceDetail> selectByInvoicePlanIds(List<Long> invoicePlanIds) {
if (invoicePlanIds == null || invoicePlanIds.isEmpty()) {
return Collections.emptyList();
}
return omsReceivableInvoiceDetailMapper.selectByInvoicePlanIds(invoicePlanIds);
}
}

View File

@ -0,0 +1,167 @@
package com.ruoyi.sip.service.impl;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.mapper.OmsReceivableBillMapper;
import com.ruoyi.sip.service.IOmsReceivableInvoiceDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.sip.mapper.OmsReceivableInvoicePlanMapper;
import com.ruoyi.sip.service.IOmsReceivableInvoicePlanService;
/**
* Service
*
* @author ruoyi
* @date 2025-12-16
*/
@Service
public class OmsReceivableInvoicePlanServiceImpl implements IOmsReceivableInvoicePlanService
{
@Autowired
private OmsReceivableInvoicePlanMapper omsReceivableInvoicePlanMapper;
@Autowired
private IOmsReceivableInvoiceDetailService detailService;
@Autowired
private OmsReceivableBillMapper billMapper;
/**
*
*
* @param id
* @return
*/
@Override
public OmsReceivableInvoicePlan selectOmsReceivableInvoicePlanById(Long id)
{
return omsReceivableInvoicePlanMapper.selectOmsReceivableInvoicePlanById(id);
}
/**
*
*
* @param omsReceivableInvoicePlan
* @return
*/
@Override
public List<OmsReceivableInvoicePlan> selectOmsReceivableInvoicePlanList(OmsReceivableInvoicePlan omsReceivableInvoicePlan)
{
return omsReceivableInvoicePlanMapper.selectOmsReceivableInvoicePlanList(omsReceivableInvoicePlan);
}
/**
*
*
* @param omsReceivableInvoicePlan
* @return
*/
@Override
public int insertOmsReceivableInvoicePlan(OmsReceivableInvoicePlan omsReceivableInvoicePlan)
{
return omsReceivableInvoicePlanMapper.insertOmsReceivableInvoicePlan(omsReceivableInvoicePlan);
}
/**
*
*
* @param omsReceivableInvoicePlan
* @return
*/
@Override
public int updateOmsReceivableInvoicePlan(OmsReceivableInvoicePlan omsReceivableInvoicePlan)
{
return omsReceivableInvoicePlanMapper.updateOmsReceivableInvoicePlan(omsReceivableInvoicePlan);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteOmsReceivableInvoicePlanByIds(String ids)
{
return omsReceivableInvoicePlanMapper.deleteOmsReceivableInvoicePlanByIds(ids);
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteOmsReceivableInvoicePlanById(Long id)
{
return omsReceivableInvoicePlanMapper.deleteOmsReceivableInvoicePlanById(id);
}
@Override
public List<OmsReceivableInvoicePlan> listByReceivableBillId(Long receivableBillId) {
OmsReceivableInvoicePlan omsReceivableInvoicePlan = new OmsReceivableInvoicePlan();
omsReceivableInvoicePlan.setReceivableBillId(receivableBillId);
List<OmsReceivableInvoicePlan> omsReceivableInvoicePlans = omsReceivableInvoicePlanMapper.selectOmsReceivableInvoicePlanList(omsReceivableInvoicePlan);
// if (CollUtil.isNotEmpty(omsReceivableInvoicePlans)) {
// List<OmsReceivableInvoiceDetail> omsPayablePaymentDetails = detailService.listByReceivableBillIdList(omsReceivableInvoicePlans.stream().map(OmsReceivableInvoicePlan::getReceivableBillId).collect(Collectors.toList()));
// Map<Long, OmsReceivableInvoiceDetail> detailMap = omsPayablePaymentDetails.stream().collect(Collectors.toMap(OmsReceivableInvoiceDetail::getInvoicePlanId, Function.identity(),
// (v1, v2) -> v1.getCreateTime().after(v2.getCreateTime()) ? v1 : v2));
// for (OmsReceivableInvoicePlan plan : omsReceivableInvoicePlans) {
// //找到最新的一条数据 如果不是退款 那么不允许再次勾选
// OmsReceivableInvoiceDetail detail = detailMap.get(plan.getId());
// if (detail != null && !OmsReceivableInvoiceDetail.PayableDetailTypeEnum.RED_RUSH.getCode().equalsIgnoreCase(detail.getInvoiceDetailType())) {
//
// plan.setDetailId(detail.getId());
// }
// }
// }
return omsReceivableInvoicePlans;
}
@Override
public void updateInvoicePlans(Long receivableBillId, List<OmsReceivableInvoicePlan> invoicePlanList) {
// 获取数据库中现有付款计划的ID
List<OmsReceivableInvoicePlan> omsReceivableInvoicePlans = listByReceivableBillId(receivableBillId);
Set<Long> existingPlanIdSet = omsReceivableInvoicePlans.stream().map(OmsReceivableInvoicePlan::getId).collect(Collectors.toSet());
// 用于存放前端传入的有效非新增或已删除的计划ID
Set<Long> incomingPlanIdSet = invoicePlanList.stream()
.filter(plan -> plan.getId() != null)
.map(OmsReceivableInvoicePlan::getId)
.collect(Collectors.toSet());
for (OmsReceivableInvoicePlan plan : invoicePlanList) {
plan.setReceivableBillId(receivableBillId);
if (plan.getId() == null) {
// 新增付款计划
plan.setCreateBy(ShiroUtils.getLoginName());
omsReceivableInvoicePlanMapper.insertOmsReceivableInvoicePlan(plan);
} else if (existingPlanIdSet.contains(plan.getId())) {
// 更新现有付款计划
omsReceivableInvoicePlanMapper.updateOmsReceivableInvoicePlan(plan);
}
// 如果plan.getId()不为null但不在existingPlanIdSet中说明是前端新添加但带有id的脏数据或者是非法数据这里不处理
}
// 删除数据库中存在但前端未提交的付款计划
existingPlanIdSet.removeAll(incomingPlanIdSet);
for (Long idToDelete : existingPlanIdSet) {
omsReceivableInvoicePlanMapper.deleteOmsReceivableInvoicePlanById(idToDelete);
}
OmsReceivableInvoicePlan payablePaymentPlan = omsReceivableInvoicePlanMapper.firstUnPayPlan(receivableBillId); // Changed from firstUnPayPlan to firstUnPayPlan
OmsReceivableBill receivableBill = new OmsReceivableBill();
receivableBill.setId(receivableBillId); // Changed from payableBillId to receivableBillId
receivableBill.setLastInvoicePlanId(payablePaymentPlan == null ? -1 : payablePaymentPlan.getId());
billMapper.updateOmsReceivableBill(receivableBill);
}
}

View File

@ -0,0 +1,138 @@
package com.ruoyi.sip.service.impl;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.sip.domain.OmsFinAttachment;
import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
import com.ruoyi.sip.service.IOmsFinAttachmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.sip.mapper.OmsReceivableReceiptDetailMapper;
import com.ruoyi.sip.domain.OmsReceivableReceiptDetail;
import com.ruoyi.sip.service.IOmsReceivableReceiptDetailService;
/**
* Service
*
* @author ruoyi
* @date 2025-12-16
*/
@Service
public class OmsReceivableReceiptDetailServiceImpl implements IOmsReceivableReceiptDetailService
{
@Autowired
private OmsReceivableReceiptDetailMapper omsReceivableReceiptDetailMapper;
@Autowired
private IOmsFinAttachmentService finAttachmentService;
/**
*
*
* @param id
* @return
*/
@Override
public OmsReceivableReceiptDetail selectOmsReceivableReceiptDetailById(Long id)
{
return omsReceivableReceiptDetailMapper.selectOmsReceivableReceiptDetailById(id);
}
/**
*
*
* @param omsReceivableReceiptDetail
* @return
*/
@Override
public List<OmsReceivableReceiptDetail> selectOmsReceivableReceiptDetailList(OmsReceivableReceiptDetail omsReceivableReceiptDetail)
{
return omsReceivableReceiptDetailMapper.selectOmsReceivableReceiptDetailList(omsReceivableReceiptDetail);
}
/**
*
*
* @param omsReceivableReceiptDetail
* @return
*/
@Override
public int insertOmsReceivableReceiptDetail(OmsReceivableReceiptDetail omsReceivableReceiptDetail)
{
return omsReceivableReceiptDetailMapper.insertOmsReceivableReceiptDetail(omsReceivableReceiptDetail);
}
/**
*
*
* @param omsReceivableReceiptDetail
* @return
*/
@Override
public int updateOmsReceivableReceiptDetail(OmsReceivableReceiptDetail omsReceivableReceiptDetail)
{
return omsReceivableReceiptDetailMapper.updateOmsReceivableReceiptDetail(omsReceivableReceiptDetail);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteOmsReceivableReceiptDetailByIds(String ids)
{
return omsReceivableReceiptDetailMapper.deleteOmsReceivableReceiptDetailByIds(ids);
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteOmsReceivableReceiptDetailById(Long id)
{
return omsReceivableReceiptDetailMapper.deleteOmsReceivableReceiptDetailById(id);
}
@Override
public List<OmsReceivableReceiptDetail> listByReceivableBillId(Long id) {
OmsReceivableReceiptDetail omsReceivableReceiptDetail = new OmsReceivableReceiptDetail();
omsReceivableReceiptDetail.setReceivableBillId(id);
List<OmsReceivableReceiptDetail> list = omsReceivableReceiptDetailMapper.list(omsReceivableReceiptDetail);
if (CollUtil.isNotEmpty(list)){
OmsFinAttachment omsFinAttachment = new OmsFinAttachment();
omsFinAttachment.setRelatedBillIdList(list.stream().map(OmsReceivableReceiptDetail::getReceiptBillId).distinct().collect(Collectors.toList()));
omsFinAttachment.setRelatedBillType(OmsFinAttachment.RelatedBillTypeEnum.RECEIPT.getCode());
omsFinAttachment.setDelFlag("0");
List<OmsFinAttachment> attachmentList = finAttachmentService.selectOmsFinAttachmentList(omsFinAttachment);
Map<Long, OmsFinAttachment> collect = attachmentList.stream().collect(Collectors.toMap(OmsFinAttachment::getRelatedBillId, Function.identity()));
for (OmsReceivableReceiptDetail payablePaymentDetail : list) {
payablePaymentDetail.setFinAttachment(collect.get(payablePaymentDetail.getReceiptBillId()));
}
}
return list;
}
@Override
public List<OmsReceivableReceiptDetail> selectReceiptPlanByIds(List<Long> allReceiptPlanIds) {
return omsReceivableReceiptDetailMapper.selectByPaymentPlanIds(allReceiptPlanIds);
}
@Override
public List<OmsReceivableReceiptDetail> listByReceivableBillIdList(List<Long> idList) {
if (CollUtil.isNotEmpty(idList)){
OmsReceivableReceiptDetail omsReceivableReceiptDetail = new OmsReceivableReceiptDetail();
omsReceivableReceiptDetail.setIdList(idList);
return omsReceivableReceiptDetailMapper.selectOmsReceivableReceiptDetailList(omsReceivableReceiptDetail);
}
return Collections.emptyList();
}
}

View File

@ -0,0 +1,309 @@
package com.ruoyi.sip.service.impl;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Comparator;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.mapper.OmsReceivableBillMapper;
import com.ruoyi.sip.service.IOmsReceivableReceiptDetailService;
import com.ruoyi.sip.service.IOmsReceivableInvoicePlanService;
import com.ruoyi.common.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.sip.mapper.OmsReceivableReceiptPlanMapper;
import com.ruoyi.sip.service.IOmsReceivableReceiptPlanService;
/**
* Service
*
* @author ruoyi
* @date 2025-12-16
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class OmsReceivableReceiptPlanServiceImpl implements IOmsReceivableReceiptPlanService
{
@Autowired
private OmsReceivableReceiptPlanMapper omsReceivableReceiptPlanMapper;
@Autowired
private OmsReceivableBillMapper billMapper;
@Autowired
private IOmsReceivableReceiptDetailService omsReceivableReceiptDetailService;
@Autowired
private IOmsReceivableInvoicePlanService invoicePlanService;
/**
*
*
* @param id
* @return
*/
@Override
public OmsReceivableReceiptPlan selectOmsReceivableReceiptPlanById(Long id)
{
return omsReceivableReceiptPlanMapper.selectOmsReceivableReceiptPlanById(id);
}
/**
*
*
* @param omsReceivableReceiptPlan
* @return
*/
@Override
public List<OmsReceivableReceiptPlan> selectOmsReceivableReceiptPlanList(OmsReceivableReceiptPlan omsReceivableReceiptPlan)
{
return omsReceivableReceiptPlanMapper.selectOmsReceivableReceiptPlanList(omsReceivableReceiptPlan);
}
/**
* ID
*
* @param receivableBillId ID
* @return
*/
@Override
public List<OmsReceivableReceiptPlan> selectOmsReceivableReceiptPlanListByReceivableBillId(Long receivableBillId)
{
List<OmsReceivableReceiptPlan> omsReceivableReceiptPlans = omsReceivableReceiptPlanMapper.selectOmsReceivableReceiptPlanListByReceivableBillId(receivableBillId);
if (CollUtil.isNotEmpty(omsReceivableReceiptPlans)) {
List<OmsReceivableReceiptDetail> omsReceivableReceiptDetails = omsReceivableReceiptDetailService.listByReceivableBillId(receivableBillId);
Map<Long, OmsReceivableReceiptDetail> detailMap = omsReceivableReceiptDetails.stream().collect(Collectors.toMap(OmsReceivableReceiptDetail::getReceiptPlanId, Function.identity(),
(v1, v2) -> v1.getCreateTime().after(v2.getCreateTime()) ? v1 : v2));
for (OmsReceivableReceiptPlan omsReceivableReceiptPlan : omsReceivableReceiptPlans) {
//找到最新的一条数据 如果不是退款 那么不允许再次勾选
OmsReceivableReceiptDetail omsReceivableReceiptDetail = detailMap.get(omsReceivableReceiptPlan.getId());
if (omsReceivableReceiptDetail != null && !OmsReceivableReceiptDetail.ReceivableDetailTypeEnum.REFUND.getCode().equalsIgnoreCase(omsReceivableReceiptDetail.getReceivableDetailType()))
omsReceivableReceiptPlan.setDetailId(omsReceivableReceiptDetail.getId());
}
}
return omsReceivableReceiptPlans;
}
/**
*
*
* @param omsReceivableReceiptPlan
* @return
*/
@Override
public int insertOmsReceivableReceiptPlan(OmsReceivableReceiptPlan omsReceivableReceiptPlan)
{
return omsReceivableReceiptPlanMapper.insertOmsReceivableReceiptPlan(omsReceivableReceiptPlan);
}
/**
*
*
* @param omsReceivableReceiptPlan
* @return
*/
@Override
public int updateOmsReceivableReceiptPlan(OmsReceivableReceiptPlan omsReceivableReceiptPlan)
{
return omsReceivableReceiptPlanMapper.updateOmsReceivableReceiptPlan(omsReceivableReceiptPlan);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteOmsReceivableReceiptPlanByIds(String ids)
{
return omsReceivableReceiptPlanMapper.deleteOmsReceivableReceiptPlanByIds(ids);
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteOmsReceivableReceiptPlanById(Long id)
{
return omsReceivableReceiptPlanMapper.deleteOmsReceivableReceiptPlanById(id);
}
/**
*
*
* @param receivableBillId ID
* @param receiptPlanList
* @return
*/
@Override
@Transactional
public void updateReceiptPlans(Long receivableBillId, List<OmsReceivableReceiptPlan> receiptPlanList) {
// 获取数据库中现有收款计划的ID
List<OmsReceivableReceiptPlan> existingPlans = omsReceivableReceiptPlanMapper.selectOmsReceivableReceiptPlanListByReceivableBillId(receivableBillId);
List<Long> existingPlanIds = existingPlans.stream().map(OmsReceivableReceiptPlan::getId).collect(Collectors.toList());
Set<Long> existingPlanIdSet = existingPlanIds.stream().collect(Collectors.toSet());
// 用于存放前端传入的有效非新增或已删除的计划ID
Set<Long> incomingPlanIdSet = receiptPlanList.stream()
.filter(plan -> plan.getId() != null)
.map(OmsReceivableReceiptPlan::getId)
.collect(Collectors.toSet());
for (OmsReceivableReceiptPlan plan : receiptPlanList) {
plan.setReceivableBillId(receivableBillId);
if (plan.getId() == null) {
// 新增收款计划
plan.setCreateBy(ShiroUtils.getLoginName());
omsReceivableReceiptPlanMapper.insertOmsReceivableReceiptPlan(plan);
} else if (existingPlanIdSet.contains(plan.getId())) {
// 更新现有收款计划
omsReceivableReceiptPlanMapper.updateOmsReceivableReceiptPlan(plan);
}
// 如果plan.getId()不为null但不在existingPlanIdSet中说明是前端新添加但带有id的脏数据或者是非法数据这里不处理
}
// 删除数据库中存在但前端未提交的收款计划
existingPlanIdSet.removeAll(incomingPlanIdSet);
for (Long idToDelete : existingPlanIdSet) {
omsReceivableReceiptPlanMapper.deleteOmsReceivableReceiptPlanById(idToDelete);
}
List<OmsReceivableReceiptPlan> allReceiptPlans = omsReceivableReceiptPlanMapper.selectOmsReceivableReceiptPlanListByReceivableBillId(receivableBillId);
OmsReceivableReceiptPlan receivableReceiptPlan = allReceiptPlans.stream()
.filter(p -> p.getDetailId() == null) // 查找未执行的收款计划
.min(Comparator.comparing(OmsReceivableReceiptPlan::getPlanReceiptDate))
.orElse(null);
OmsReceivableBill receivableBill = new OmsReceivableBill();
receivableBill.setId(receivableBillId);
receivableBill.setLastReceiptPlanId(receivableReceiptPlan == null ? -1L : receivableReceiptPlan.getId());
billMapper.updateOmsReceivableBill(receivableBill);
}
/**
*
*
* @param receivableBillId ID
* @return
*/
@Override
@Transactional
public void syncReceiptToInvoicePlan(Long receivableBillId) {
List<OmsReceivableInvoicePlan> invoicePlans = invoicePlanService.selectOmsReceivableInvoicePlanList(new OmsReceivableInvoicePlan() {{
setReceivableBillId(receivableBillId);
}});
List<OmsReceivableReceiptPlan> receiptPlans = selectOmsReceivableReceiptPlanListByReceivableBillId(receivableBillId);
boolean hasExecutedInvoice = invoicePlans.stream().anyMatch(p -> p.getDetailId() != null);
if (!hasExecutedInvoice) {
List<OmsReceivableInvoicePlan> newPlans = convertReceiptToInvoice(receiptPlans, receivableBillId);
updateInvoicePlan(receivableBillId, newPlans);
} else {
List<OmsReceivableInvoicePlan> executedInvoices = invoicePlans.stream()
.filter(p -> p.getDetailId() != null).collect(Collectors.toList());
List<OmsReceivableReceiptPlan> executedReceipts = receiptPlans.stream()
.filter(p -> p.getDetailId() != null).collect(Collectors.toList());
List<OmsReceivableReceiptPlan> unmatchedExecutedReceipts = new ArrayList<>(executedReceipts);
for (OmsReceivableInvoicePlan invoice : executedInvoices) {
boolean found = false;
Iterator<OmsReceivableReceiptPlan> it = unmatchedExecutedReceipts.iterator();
while (it.hasNext()) {
OmsReceivableReceiptPlan receipt = it.next();
if (compareDates(invoice.getPlanInvoiceDate(), receipt.getPlanReceiptDate()) == 0 &&
invoice.getPlanAmount().compareTo(receipt.getPlanAmount()) == 0) {
it.remove();
found = true;
break;
}
}
if (!found) {
throw new ServiceException("因收款计划表与开票计划表中已收款/开票数据已不一致,所以无法关联开票计划");
}
}
List<OmsReceivableReceiptPlan> unexecutedReceipts = receiptPlans.stream()
.filter(p -> p.getDetailId() == null).collect(Collectors.toList());
List<OmsReceivableReceiptPlan> toConvert = new ArrayList<>();
toConvert.addAll(unmatchedExecutedReceipts);
toConvert.addAll(unexecutedReceipts);
List<OmsReceivableInvoicePlan> newPlans = convertReceiptToInvoice(toConvert, receivableBillId);
List<OmsReceivableInvoicePlan> finalPlans = new ArrayList<>(executedInvoices);
finalPlans.addAll(newPlans);
updateInvoicePlan(receivableBillId, finalPlans);
}
}
@Override
public OmsReceivableReceiptPlan firstUnPayPlan(Long id) {
return omsReceivableReceiptPlanMapper.firstUnPayPlan(id);
}
/**
*
*
* @param receivableBillId ID
* @param invoicePlanList
*/
private void updateInvoicePlan(Long receivableBillId, List<OmsReceivableInvoicePlan> invoicePlanList) {
// 删除原有的开票计划
OmsReceivableInvoicePlan invoicePlanCriteria = new OmsReceivableInvoicePlan();
invoicePlanCriteria.setReceivableBillId(receivableBillId);
List<OmsReceivableInvoicePlan> existingPlans = invoicePlanService.selectOmsReceivableInvoicePlanList(invoicePlanCriteria);
// Collect IDs of existing plans to delete them
if (!existingPlans.isEmpty()) {
String ids = existingPlans.stream()
.map(plan -> plan.getId().toString())
.reduce((a, b) -> a + "," + b)
.orElse("");
if (!ids.isEmpty()) {
invoicePlanService.deleteOmsReceivableInvoicePlanByIds(ids);
}
}
// 批量插入新的开票计划
for (OmsReceivableInvoicePlan plan : invoicePlanList) {
plan.setReceivableBillId(receivableBillId);
invoicePlanService.insertOmsReceivableInvoicePlan(plan);
}
}
private List<OmsReceivableInvoicePlan> convertReceiptToInvoice(List<OmsReceivableReceiptPlan> receiptPlans, Long receivableBillId) {
List<OmsReceivableInvoicePlan> list = new ArrayList<>();
for (OmsReceivableReceiptPlan r : receiptPlans) {
OmsReceivableInvoicePlan i = new OmsReceivableInvoicePlan();
i.setReceivableBillId(receivableBillId);
i.setPlanInvoiceDate(r.getPlanReceiptDate());
i.setPlanAmount(r.getPlanAmount());
i.setPlanRate(r.getPlanRate());
i.setDetailId(null);
i.setRemark(r.getRemark());
i.setCreateBy(ShiroUtils.getUserId().toString());
list.add(i);
}
return list;
}
private int compareDates(Date d1, Date d2) {
if (d1 == null && d2 == null) return 0;
if (d1 == null) return -1;
if (d2 == null) return 1;
return d1.compareTo(d2);
}
}

View File

@ -0,0 +1,67 @@
package com.ruoyi.sip.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
*
* HX + YYMMDD +
*
* @author zghz
* @date 2025-12-16
*/
public class WriteOffCodeGenerator {
private static final String PREFIX = "HX";
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyMMdd");
// 用于生成序列号的锁和计数器
private static final Object lock = new Object();
private static int sequenceNumber = 0;
/**
*
*
* @return
*/
public static String generateWriteOffCode() {
synchronized (lock) {
// 获取当前日期
String dateStr = DATE_FORMAT.format(new Date());
// 递增序列号
sequenceNumber++;
// 重置序列号 如果超过四位数则重置(实际使用中可能需要更复杂的逻辑来处理)
if (sequenceNumber > 9999) {
sequenceNumber = 1;
}
// 格式化四位序列号
String sequenceStr = String.format("%04d", sequenceNumber);
return PREFIX + dateStr + sequenceStr;
}
}
/**
*
*/
public static void resetSequence() {
synchronized (lock) {
sequenceNumber = 0;
}
}
/**
*
*
* @param number
*/
public static void setSequenceNumber(int number) {
synchronized (lock) {
sequenceNumber = number;
}
}
}

View File

@ -0,0 +1,128 @@
<?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

@ -0,0 +1,108 @@
<?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.OmsPayableWriteOffMapper">
<resultMap type="com.ruoyi.sip.domain.OmsPayableWriteOff" id="OmsPayableWriteOffResult">
<result property="id" column="id" />
<result property="writeOffCode" column="write_off_code" />
<result property="writeOffType" column="write_off_type" />
<result property="paymentBillCode" column="payment_bill_code" />
<result property="vendorCode" column="vendor_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="writeOffTime" column="write_off_time" />
<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="selectOmsPayableWriteOffVo">
select id, write_off_code, write_off_type, payment_bill_code, vendor_code,
write_off_amount, write_off_amount_without_tax, write_off_tax_amount, write_off_time,
remark, create_by, create_time, update_by, update_time
from oms_payable_write_off
</sql>
<select id="selectOmsPayableWriteOffById" parameterType="Long" resultMap="OmsPayableWriteOffResult">
<include refid="selectOmsPayableWriteOffVo"/>
where id = #{id}
</select>
<select id="selectOmsPayableWriteOffList" parameterType="com.ruoyi.sip.domain.OmsPayableWriteOff" resultMap="OmsPayableWriteOffResult">
<include refid="selectOmsPayableWriteOffVo"/>
<where>
<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="paymentBillCode != null and paymentBillCode != ''"> and payment_bill_code = #{paymentBillCode}</if>
<if test="vendorCode != null and vendorCode != ''"> and vendor_code = #{vendorCode}</if>
</where>
</select>
<insert id="insertOmsPayableWriteOff" parameterType="com.ruoyi.sip.domain.OmsPayableWriteOff" useGeneratedKeys="true" keyProperty="id">
insert into oms_payable_write_off
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="writeOffCode != null">write_off_code,</if>
<if test="writeOffType != null">write_off_type,</if>
<if test="paymentBillCode != null">payment_bill_code,</if>
<if test="vendorCode != null">vendor_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="writeOffTime != null">write_off_time,</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="writeOffCode != null">#{writeOffCode},</if>
<if test="writeOffType != null">#{writeOffType},</if>
<if test="paymentBillCode != null">#{paymentBillCode},</if>
<if test="vendorCode != null">#{vendorCode},</if>
<if test="writeOffAmount != null">#{writeOffAmount},</if>
<if test="writeOffAmountWithoutTax != null">#{writeOffAmountWithoutTax},</if>
<if test="writeOffTaxAmount != null">#{writeOffTaxAmount},</if>
<if test="writeOffTime != null">#{writeOffTime},</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="updateOmsPayableWriteOff" parameterType="com.ruoyi.sip.domain.OmsPayableWriteOff">
update oms_payable_write_off
<trim prefix="SET" suffixOverrides=",">
<if test="writeOffCode != null">write_off_code = #{writeOffCode},</if>
<if test="writeOffType != null">write_off_type = #{writeOffType},</if>
<if test="paymentBillCode != null">payment_bill_code = #{paymentBillCode},</if>
<if test="vendorCode != null">vendor_code = #{vendorCode},</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="writeOffTime != null">write_off_time = #{writeOffTime},</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="deleteOmsPayableWriteOffById" parameterType="Long">
delete from oms_payable_write_off where id = #{id}
</delete>
<delete id="deleteOmsPayableWriteOffByIds" parameterType="String">
delete from oms_payable_write_off where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,454 @@
<?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.OmsReceiptBillMapper">
<resultMap type="com.ruoyi.sip.domain.OmsReceiptBill" id="OmsReceiptBillMap">
<result property="id" column="id"/>
<result property="receiptBillCode" column="receipt_bill_code"/>
<result property="receiptBillType" column="receipt_bill_type"/>
<result property="receiptTime" column="receipt_time"/>
<result property="actualReceiptTime" column="actual_receipt_time"/>
<result property="partnerCode" column="partner_code"/>
<result property="orderCode" column="order_code"/>
<result property="totalPriceWithTax" column="total_price_with_tax"/>
<result property="totalPriceWithoutTax" column="total_price_without_tax"/>
<result property="taxAmount" column="tax_amount"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="remark" column="remark"/>
<result property="delFlag" column="del_flag"/>
<result property="projectCode" column="project_code"/>
<result property="projectName" column="project_name"/>
<result property="receiptStatus" column="receipt_status"/>
<result property="approveStatus" column="approve_status"/>
<result property="approveNode" column="approve_node"/>
<result property="approveTime" column="approve_time"/>
<result property="receiptMethod" column="receipt_method"/>
<result property="receiptAccountName" column="receipt_account_name"/>
<result property="receiptBankNumber" column="receipt_bank_number"/>
<result property="receiptBankOpenAddress" column="receipt_bank_open_address"/>
<result property="bankNumber" column="bank_number"/>
<result property="refundStatus" column="refund_status"/>
</resultMap>
<!-- 基本字段 -->
<sql id="Base_Column_List">
id, receipt_bill_code, 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
</sql>
<!--通过实体作为筛选条件查询-->
<select id="queryAll" resultMap="OmsReceiptBillMap">
select
<include refid="Base_Column_List"/>
from oms_receipt_bill
<where>
<if test="id != null">
and id = #{id}
</if>
<if test="receiptBillCode != null and receiptBillCode != ''">
and receipt_bill_code = #{receiptBillCode}
</if>
<if test="receiptBillType != null and receiptBillType != ''">
and receipt_bill_type = #{receiptBillType}
</if>
<if test="receiptTime != null">
and receipt_time = #{receiptTime}
</if>
<if test="actualReceiptTime != null">
and actual_receipt_time = #{actualReceiptTime}
</if>
<if test="partnerCode != null and partnerCode != ''">
and partner_code = #{partnerCode}
</if>
<if test="orderCode != null and orderCode != ''">
and order_code = #{orderCode}
</if>
<if test="totalPriceWithTax != null">
and total_price_with_tax = #{totalPriceWithTax}
</if>
<if test="totalPriceWithoutTax != null">
and total_price_without_tax = #{totalPriceWithoutTax}
</if>
<if test="taxAmount != null">
and tax_amount = #{taxAmount}
</if>
<if test="createBy != null and createBy != ''">
and create_by = #{createBy}
</if>
<if test="createTime != null">
and create_time = #{createTime}
</if>
<if test="updateBy != null and updateBy != ''">
and update_by = #{updateBy}
</if>
<if test="updateTime != null">
and update_time = #{updateTime}
</if>
<if test="remark != null and remark != ''">
and remark = #{remark}
</if>
<if test="delFlag != null and delFlag != ''">
and del_flag = #{delFlag}
</if>
<if test="projectCode != null and projectCode != ''">
and project_code = #{projectCode}
</if>
<if test="projectName != null and projectName != ''">
and project_name = #{projectName}
</if>
<if test="receiptStatus != null and receiptStatus != ''">
and receipt_status = #{receiptStatus}
</if>
<if test="approveStatus != null and approveStatus != ''">
and approve_status = #{approveStatus}
</if>
<if test="approveNode != null and approveNode != ''">
and approve_node = #{approveNode}
</if>
<if test="approveTime != null">
and approve_time = #{approveTime}
</if>
<if test="receiptMethod != null and receiptMethod != ''">
and receipt_method = #{receiptMethod}
</if>
<if test="receiptAccountName != null and receiptAccountName != ''">
and receipt_account_name = #{receiptAccountName}
</if>
<if test="receiptBankNumber != null and receiptBankNumber != ''">
and receipt_bank_number = #{receiptBankNumber}
</if>
<if test="receiptBankOpenAddress != null and receiptBankOpenAddress != ''">
and receipt_bank_open_address = #{receiptBankOpenAddress}
</if>
<if test="bankNumber != null and bankNumber != ''">
and bank_number = #{bankNumber}
</if>
<if test="refundStatus != null and refundStatus != ''">
and refund_status = #{refundStatus}
</if>
</where>
</select>
<!--根据ID查详情-->
<select id="queryById" parameterType="Integer" resultMap="OmsReceiptBillMap">
SELECT id,
receipt_bill_code,
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
FROM oms_receipt_bill
WHERE id = #{id}
LIMIT 1
</select>
<select id="selectMaxCodeByPrefix" resultType="java.lang.Integer">
SELECT IFNULL(MAX(CAST(SUBSTRING(receipt_bill_code, LENGTH(#{prefix}) + 1) AS SIGNED)), 0)
FROM oms_receipt_bill
WHERE receipt_bill_code LIKE CONCAT(#{prefix}, '%')
</select>
<!--新增所有列-->
<insert id="insert" keyProperty="id" useGeneratedKeys="true">
INSERT INTO oms_receipt_bill
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="receiptBillCode != null and receiptBillCode != ''">
receipt_bill_code,
</if>
<if test="receiptBillType != null and receiptBillType != ''">
receipt_bill_type,
</if>
<if test="receiptTime != null">
receipt_time,
</if>
<if test="actualReceiptTime != null">
actual_receipt_time,
</if>
<if test="partnerCode != null and partnerCode != ''">
partner_code,
</if>
<if test="orderCode != null and orderCode != ''">
order_code,
</if>
<if test="totalPriceWithTax != null">
total_price_with_tax,
</if>
<if test="totalPriceWithoutTax != null">
total_price_without_tax,
</if>
<if test="taxAmount != null">
tax_amount,
</if>
<if test="createBy != null and createBy != ''">
create_by,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="updateBy != null and updateBy != ''">
update_by,
</if>
<if test="updateTime != null">
update_time,
</if>
<if test="remark != null and remark != ''">
remark,
</if>
<if test="delFlag != null and delFlag != ''">
del_flag,
</if>
<if test="projectCode != null and projectCode != ''">
project_code,
</if>
<if test="projectName != null and projectName != ''">
project_name,
</if>
<if test="receiptStatus != null and receiptStatus != ''">
receipt_status,
</if>
<if test="approveStatus != null and approveStatus != ''">
approve_status,
</if>
<if test="approveNode != null and approveNode != ''">
approve_node,
</if>
<if test="approveTime != null">
approve_time,
</if>
<if test="receiptMethod != null and receiptMethod != ''">
receipt_method,
</if>
<if test="receiptAccountName != null and receiptAccountName != ''">
receipt_account_name,
</if>
<if test="receiptBankNumber != null and receiptBankNumber != ''">
receipt_bank_number,
</if>
<if test="receiptBankOpenAddress != null and receiptBankOpenAddress != ''">
receipt_bank_open_address,
</if>
<if test="bankNumber != null and bankNumber != ''">
bank_number,
</if>
<if test="refundStatus != null and refundStatus != ''">
refund_status,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="receiptBillCode != null and receiptBillCode != ''">
#{receiptBillCode},
</if>
<if test="receiptBillType != null and receiptBillType != ''">
#{receiptBillType},
</if>
<if test="receiptTime != null">
#{receiptTime},
</if>
<if test="actualReceiptTime != null">
#{actualReceiptTime},
</if>
<if test="partnerCode != null and partnerCode != ''">
#{partnerCode},
</if>
<if test="orderCode != null and orderCode != ''">
#{orderCode},
</if>
<if test="totalPriceWithTax != null">
#{totalPriceWithTax},
</if>
<if test="totalPriceWithoutTax != null">
#{totalPriceWithoutTax},
</if>
<if test="taxAmount != null">
#{taxAmount},
</if>
<if test="createBy != null and createBy != ''">
#{createBy},
</if>
<if test="createTime != null">
#{createTime},
</if>
<if test="updateBy != null and updateBy != ''">
#{updateBy},
</if>
<if test="updateTime != null">
#{updateTime},
</if>
<if test="remark != null and remark != ''">
#{remark},
</if>
<if test="delFlag != null and delFlag != ''">
#{delFlag},
</if>
<if test="projectCode != null and projectCode != ''">
#{projectCode},
</if>
<if test="projectName != null and projectName != ''">
#{projectName},
</if>
<if test="receiptStatus != null and receiptStatus != ''">
#{receiptStatus},
</if>
<if test="approveStatus != null and approveStatus != ''">
#{approveStatus},
</if>
<if test="approveNode != null and approveNode != ''">
#{approveNode},
</if>
<if test="approveTime != null">
#{approveTime},
</if>
<if test="receiptMethod != null and receiptMethod != ''">
#{receiptMethod},
</if>
<if test="receiptAccountName != null and receiptAccountName != ''">
#{receiptAccountName},
</if>
<if test="receiptBankNumber != null and receiptBankNumber != ''">
#{receiptBankNumber},
</if>
<if test="receiptBankOpenAddress != null and receiptBankOpenAddress != ''">
#{receiptBankOpenAddress},
</if>
<if test="bankNumber != null and bankNumber != ''">
#{bankNumber},
</if>
<if test="refundStatus != null and refundStatus != ''">
#{refundStatus},
</if>
</trim>
</insert>
<!--通过主键修改数据-->
<update id="update">
UPDATE oms_receipt_bill
<trim prefix="SET" suffixOverrides=",">
<if test="receiptBillCode != null and receiptBillCode != ''">
receipt_bill_code = #{receiptBillCode},
</if>
<if test="receiptBillType != null and receiptBillType != ''">
receipt_bill_type = #{receiptBillType},
</if>
<if test="receiptTime != null">
receipt_time = #{receiptTime},
</if>
<if test="actualReceiptTime != null">
actual_receipt_time = #{actualReceiptTime},
</if>
<if test="partnerCode != null and partnerCode != ''">
partner_code = #{partnerCode},
</if>
<if test="orderCode != null and orderCode != ''">
order_code = #{orderCode},
</if>
<if test="totalPriceWithTax != null">
total_price_with_tax = #{totalPriceWithTax},
</if>
<if test="totalPriceWithoutTax != null">
total_price_without_tax = #{totalPriceWithoutTax},
</if>
<if test="taxAmount != null">
tax_amount = #{taxAmount},
</if>
<if test="createBy != null and createBy != ''">
create_by = #{createBy},
</if>
<if test="createTime != null">
create_time = #{createTime},
</if>
<if test="updateBy != null and updateBy != ''">
update_by = #{updateBy},
</if>
<if test="updateTime != null">
update_time = #{updateTime},
</if>
<if test="remark != null and remark != ''">
remark = #{remark},
</if>
<if test="delFlag != null and delFlag != ''">
del_flag = #{delFlag},
</if>
<if test="projectCode != null and projectCode != ''">
project_code = #{projectCode},
</if>
<if test="projectName != null and projectName != ''">
project_name = #{projectName},
</if>
<if test="receiptStatus != null and receiptStatus != ''">
receipt_status = #{receiptStatus},
</if>
<if test="approveStatus != null and approveStatus != ''">
approve_status = #{approveStatus},
</if>
<if test="approveNode != null and approveNode != ''">
approve_node = #{approveNode},
</if>
<if test="approveTime != null">
approve_time = #{approveTime},
</if>
<if test="receiptMethod != null and receiptMethod != ''">
receipt_method = #{receiptMethod},
</if>
<if test="receiptAccountName != null and receiptAccountName != ''">
receipt_account_name = #{receiptAccountName},
</if>
<if test="receiptBankNumber != null and receiptBankNumber != ''">
receipt_bank_number = #{receiptBankNumber},
</if>
<if test="receiptBankOpenAddress != null and receiptBankOpenAddress != ''">
receipt_bank_open_address = #{receiptBankOpenAddress},
</if>
<if test="bankNumber != null and bankNumber != ''">
bank_number = #{bankNumber},
</if>
<if test="refundStatus != null and refundStatus != ''">
refund_status = #{refundStatus},
</if>
</trim>
WHERE id = #{id}
</update>
<!--通过主键删除-->
<delete id="deleteById">
DELETE
FROM oms_receipt_bill
WHERE id = #{id}
</delete>
<!--通过id批量删除-->
<delete id="batchRemove">
delete from oms_receipt_bill where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,190 @@
<?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.OmsReceivableBillMapper">
<resultMap type="com.ruoyi.sip.domain.OmsReceivableBill" id="OmsReceivableBillResult">
<result property="id" column="id" />
<result property="receivableBillCode" column="receivable_bill_code" />
<result property="lastReceiptPlanId" column="last_receipt_plan_id" />
<result property="lastInvoicePlanId" column="last_invoice_plan_id" />
<result property="partnerCode" column="partner_code" />
<result property="partnerName" column="partner_name" />
<result property="orderCode" column="order_code" />
<result property="inventoryCode" column="inventory_code" />
<result property="productType" column="product_type" />
<result property="totalPriceWithTax" column="total_price_with_tax" />
<result property="totalPriceWithoutTax" column="total_price_without_tax" />
<result property="taxRate" column="tax_rate" />
<result property="taxAmount" column="tax_amount" />
<result property="receivedAmount" column="received_amount" />
<result property="unreceivedAmount" column="unreceived_amount" />
<result property="invoicedAmount" column="invoiced_amount" />
<result property="uninvoicedAmount" column="uninvoiced_amount" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
</resultMap>
<sql id="selectOmsReceivableBillVo">
select t1.id, t1.receivable_bill_code, t1.last_receipt_plan_id, t1.last_invoice_plan_id, t1.partner_code, t1.partner_name, t1.order_code, t1.inventory_code, t1.product_type,
t1.total_price_with_tax, t1.total_price_without_tax, t1.tax_rate, t1.tax_amount, t1.received_amount, t1.unreceived_amount,
t1.invoiced_amount, t1.uninvoiced_amount, t1.create_by, t1.create_time, t1.update_by, t1.update_time, t1.remark, t1.del_flag
,t3.project_name, t3.project_code
,t4.plan_amount,t4.plan_receipt_date
from oms_receivable_bill t1
left join project_order_info t2 on t1.order_code=t2.order_code
left join project_info t3 on t2.project_id=t3.id
left join oms_receivable_receipt_plan t4 on t1.last_receipt_plan_id=t4.id
</sql>
<select id="selectOmsReceivableBillById" parameterType="Long" resultMap="OmsReceivableBillResult">
<include refid="selectOmsReceivableBillVo"/>
where t1.id = #{id}
</select>
<select id="selectOmsReceivableBillList" parameterType="com.ruoyi.sip.domain.OmsReceivableBill" resultMap="OmsReceivableBillResult">
<include refid="selectOmsReceivableBillVo"/>
<where>
<if test="receivableBillCode != null and receivableBillCode != ''"> and t1.receivable_bill_code like concat('%', #{receivableBillCode}, '%')</if>
<if test="idList != null and idList.size>0"> and t1.id in
<foreach item="item" collection="idList" separator="," open="(" close=")">
#{item}
</foreach>
</if>
<if test="partnerCode != null and partnerCode != ''"> and t1.partner_code = #{partnerCode}</if>
<if test="partnerName != null and partnerName != ''"> and t1.partner_name like concat('%', #{partnerName}, '%')</if>
<if test="orderCode != null and orderCode != ''"> and t1.order_code = #{orderCode}</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="createBy != null and createBy != ''"> and t1.create_by = #{createBy}</if>
and t1.del_flag = '0'
</where>
</select>
<insert id="insertOmsReceivableBill" parameterType="com.ruoyi.sip.domain.OmsReceivableBill" useGeneratedKeys="true" keyProperty="id">
insert into oms_receivable_bill
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="receivableBillCode != null and receivableBillCode != ''">receivable_bill_code,</if>
<if test="lastReceiptPlanId != null">last_receipt_plan_id,</if>
<if test="lastInvoicePlanId != null">last_invoice_plan_id,</if>
<if test="partnerCode != null and partnerCode != ''">partner_code,</if>
<if test="partnerName != null and partnerName != ''">partner_name,</if>
<if test="orderCode != null and orderCode != ''">order_code,</if>
<if test="inventoryCode != null and inventoryCode != ''">inventory_code,</if>
<if test="productType != null and productType != ''">product_type,</if>
<if test="totalPriceWithTax != null">total_price_with_tax,</if>
<if test="totalPriceWithoutTax != null">total_price_without_tax,</if>
<if test="taxRate != null">tax_rate,</if>
<if test="taxAmount != null">tax_amount,</if>
<if test="receivedAmount != null">received_amount,</if>
<if test="unreceivedAmount != null">unreceived_amount,</if>
<if test="invoicedAmount != null">invoiced_amount,</if>
<if test="uninvoicedAmount != null">uninvoiced_amount,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null and updateBy != ''">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="remark != null and remark != ''">remark,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="receivableBillCode != null and receivableBillCode != ''">#{receivableBillCode},</if>
<if test="lastReceiptPlanId != null">#{lastReceiptPlanId},</if>
<if test="lastInvoicePlanId != null">#{lastInvoicePlanId},</if>
<if test="partnerCode != null and partnerCode != ''">#{partnerCode},</if>
<if test="partnerName != null and partnerName != ''">#{partnerName},</if>
<if test="orderCode != null and orderCode != ''">#{orderCode},</if>
<if test="inventoryCode != null and inventoryCode != ''">#{inventoryCode},</if>
<if test="productType != null and productType != ''">#{productType},</if>
<if test="totalPriceWithTax != null">#{totalPriceWithTax},</if>
<if test="totalPriceWithoutTax != null">#{totalPriceWithoutTax},</if>
<if test="taxRate != null">#{taxRate},</if>
<if test="taxAmount != null">#{taxAmount},</if>
<if test="receivedAmount != null">#{receivedAmount},</if>
<if test="unreceivedAmount != null">#{unreceivedAmount},</if>
<if test="invoicedAmount != null">#{invoicedAmount},</if>
<if test="uninvoicedAmount != null">#{uninvoicedAmount},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null and updateBy != ''">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="remark != null and remark != ''">#{remark},</if>
</trim>
</insert>
<update id="updateOmsReceivableBill" parameterType="com.ruoyi.sip.domain.OmsReceivableBill">
update oms_receivable_bill
<trim prefix="SET" suffixOverrides=",">
<if test="receivableBillCode != null and receivableBillCode != ''">receivable_bill_code = #{receivableBillCode},</if>
<if test="lastReceiptPlanId != null">last_receipt_plan_id = #{lastReceiptPlanId},</if>
<if test="lastInvoicePlanId != null">last_invoice_plan_id = #{lastInvoicePlanId},</if>
<if test="partnerCode != null and partnerCode != ''">partner_code = #{partnerCode},</if>
<if test="partnerName != null and partnerName != ''">partner_name = #{partnerName},</if>
<if test="orderCode != null and orderCode != ''">order_code = #{orderCode},</if>
<if test="inventoryCode != null and inventoryCode != ''">inventory_code = #{inventoryCode},</if>
<if test="productType != null and productType != ''">product_type = #{productType},</if>
<if test="totalPriceWithTax != null">total_price_with_tax = #{totalPriceWithTax},</if>
<if test="totalPriceWithoutTax != null">total_price_without_tax = #{totalPriceWithoutTax},</if>
<if test="taxRate != null">tax_rate = #{taxRate},</if>
<if test="taxAmount != null">tax_amount = #{taxAmount},</if>
<if test="receivedAmount != null">received_amount = #{receivedAmount},</if>
<if test="unreceivedAmount != null">unreceived_amount = #{unreceivedAmount},</if>
<if test="invoicedAmount != null">invoiced_amount = #{invoicedAmount},</if>
<if test="uninvoicedAmount != null">uninvoiced_amount = #{uninvoicedAmount},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteOmsReceivableBillById" parameterType="Long">
update oms_receivable_bill set del_flag = '2' where id = #{id}
</delete>
<delete id="deleteOmsReceivableBillByIds" parameterType="String">
update oms_receivable_bill set del_flag = '2' where id in
<foreach item="id" collection="ids.split(',')" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<select id="selectMaxCodeByPrefix" parameterType="String" resultType="java.lang.Integer">
SELECT COALESCE(MAX(CAST(SUBSTRING(receivable_bill_code, LENGTH(#{codePrefix}) + 1) AS UNSIGNED)), 0)
FROM oms_receivable_bill
WHERE receivable_bill_code LIKE CONCAT(#{codePrefix}, '%')
AND receivable_bill_code REGEXP CONCAT('^', #{codePrefix}, '[0-9]+$')
</select>
<update id="updateBatchReceivableBillInvoiceInfo" parameterType="java.util.List">
<foreach collection="list" item="item" separator=";">
UPDATE oms_receivable_bill
<set>
<if test="item.invoicedAmount != null">invoiced_amount = #{item.invoicedAmount},</if>
<if test="item.uninvoicedAmount != null">uninvoiced_amount = #{item.uninvoicedAmount},</if>
<if test="item.lastInvoicePlanId != null">last_invoice_plan_id = #{item.lastInvoicePlanId},</if>
<if test="item.updateTime != null">update_time = #{item.updateTime},</if>
<if test="item.updateBy != null and item.updateBy != ''">update_by = #{item.updateBy},</if>
</set>
WHERE id = #{item.id}
</foreach>
</update>
<update id="updateBatchReceivableBillReceiptInfo">
<foreach collection="list" item="item" separator=";">
UPDATE oms_receivable_bill
SET
last_receipt_plan_id = #{item.lastReceiptPlanId},
received_amount = #{item.receivedAmount},
unreceived_amount = #{item.unreceivedAmount},
update_time = NOW(),
update_by = #{item.updateBy}
WHERE id = #{item.id}
</foreach>
</update>
</mapper>

View File

@ -0,0 +1,127 @@
<?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.OmsReceivableInvoiceDetailMapper">
<resultMap type="com.ruoyi.sip.domain.OmsReceivableInvoiceDetail" id="OmsReceivableInvoiceDetailResult">
<result property="id" column="id" />
<result property="invoicePlanId" column="invoice_plan_id" />
<result property="receivableBillId" column="receivable_bill_id" />
<result property="invoiceTime" column="invoice_time" />
<result property="invoiceAmount" column="invoice_amount" />
<result property="invoiceRate" column="invoice_rate" />
<result property="invoiceBillCode" column="invoice_bill_code" />
<result property="remark" column="remark" />
<result property="createTime" column="create_time" />
<result property="createBy" column="create_by" />
<result property="updateTime" column="update_time" />
<result property="updateBy" column="update_by" />
</resultMap>
<sql id="selectOmsReceivableInvoiceDetailVo">
select id, invoice_plan_id, receivable_bill_id, invoice_time, invoice_amount, invoice_rate, invoice_bill_code, remark, create_time, create_by, update_time, update_by
from oms_receivable_invoice_detail
</sql>
<select id="selectOmsReceivableInvoiceDetailById" parameterType="Long" resultMap="OmsReceivableInvoiceDetailResult">
<include refid="selectOmsReceivableInvoiceDetailVo"/>
where id = #{id}
</select>
<select id="selectOmsReceivableInvoiceDetailList" parameterType="com.ruoyi.sip.domain.OmsReceivableInvoiceDetail" resultMap="OmsReceivableInvoiceDetailResult">
<include refid="selectOmsReceivableInvoiceDetailVo"/>
<where>
<if test="invoicePlanId != null "> and invoice_plan_id = #{invoicePlanId}</if>
<if test="receivableBillId != null "> and receivable_bill_id = #{receivableBillId}</if>
<if test="invoiceTime != null "> and invoice_time = #{invoiceTime}</if>
<if test="invoiceAmount != null "> and invoice_amount = #{invoiceAmount}</if>
<if test="invoiceRate != null "> and invoice_rate = #{invoiceRate}</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''"> and invoice_bill_code = #{invoiceBillCode}</if>
<if test="remark != null and remark != ''"> and remark like concat('%', #{remark}, '%')</if>
</where>
</select>
<select id="listByReceivableBillIdList" resultType="com.ruoyi.sip.domain.OmsReceivableInvoiceDetail">
select
<include refid="selectOmsReceivableInvoiceDetailVo"/>
<where>
<if test="list != null and list.size() > 0">
and receivable_bill_id in
<foreach item="item" collection="list" separator="," open="(" close=")" index="index">
#{item}
</foreach>
</if>
</where>
</select>
<select id="selectByInvoicePlanIds" resultType="com.ruoyi.sip.domain.OmsReceivableInvoiceDetail">
select
<include refid="selectOmsReceivableInvoiceDetailVo"/>
<where>
<if test="list != null and list.size() > 0">
and invoice_plan_id in
<foreach item="item" collection="list" separator="," open="(" close=")" index="index">
#{item}
</foreach>
</if>
</where>
order by create_time desc
</select>
<insert id="insertOmsReceivableInvoiceDetail" parameterType="com.ruoyi.sip.domain.OmsReceivableInvoiceDetail" useGeneratedKeys="true" keyProperty="id">
insert into oms_receivable_invoice_detail
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="invoicePlanId != null">invoice_plan_id,</if>
<if test="receivableBillId != null">receivable_bill_id,</if>
<if test="invoiceTime != null">invoice_time,</if>
<if test="invoiceAmount != null">invoice_amount,</if>
<if test="invoiceRate != null">invoice_rate,</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''">invoice_bill_code,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="createTime != null">create_time,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="updateBy != null and updateBy != ''">update_by,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="invoicePlanId != null">#{invoicePlanId},</if>
<if test="receivableBillId != null">#{receivableBillId},</if>
<if test="invoiceTime != null">#{invoiceTime},</if>
<if test="invoiceAmount != null">#{invoiceAmount},</if>
<if test="invoiceRate != null">#{invoiceRate},</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''">#{invoiceBillCode},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="createTime != null">#{createTime},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="updateBy != null and updateBy != ''">#{updateBy},</if>
</trim>
</insert>
<update id="updateOmsReceivableInvoiceDetail" parameterType="com.ruoyi.sip.domain.OmsReceivableInvoiceDetail">
update oms_receivable_invoice_detail
<trim prefix="SET" suffixOverrides=",">
<if test="invoicePlanId != null">invoice_plan_id = #{invoicePlanId},</if>
<if test="receivableBillId != null">receivable_bill_id = #{receivableBillId},</if>
<if test="invoiceTime != null">invoice_time = #{invoiceTime},</if>
<if test="invoiceAmount != null">invoice_amount = #{invoiceAmount},</if>
<if test="invoiceRate != null">invoice_rate = #{invoiceRate},</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''">invoice_bill_code = #{invoiceBillCode},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteOmsReceivableInvoiceDetailById" parameterType="Long">
delete from oms_receivable_invoice_detail where id = #{id}
</delete>
<delete id="deleteOmsReceivableInvoiceDetailByIds" parameterType="String">
delete from oms_receivable_invoice_detail where id in
<foreach item="id" collection="ids.split(',')" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,101 @@
<?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.OmsReceivableInvoicePlanMapper">
<resultMap type="com.ruoyi.sip.domain.OmsReceivableInvoicePlan" id="OmsReceivableInvoicePlanResult">
<result property="id" column="id" />
<result property="receivableBillId" column="receivable_bill_id" />
<result property="planInvoiceDate" column="plan_invoice_date" />
<result property="planAmount" column="plan_amount" />
<result property="planRate" column="plan_rate" />
<result property="remark" column="remark" />
<result property="createTime" column="create_time" />
<result property="createBy" column="create_by" />
<result property="updateTime" column="update_time" />
<result property="updateBy" column="update_by" />
</resultMap>
<sql id="selectOmsReceivableInvoicePlanVo">
select id, receivable_bill_id, plan_invoice_date, plan_amount, plan_rate, remark, create_time, create_by, update_time
from oms_receivable_invoice_plan
</sql>
<select id="selectOmsReceivableInvoicePlanById" parameterType="Long" resultMap="OmsReceivableInvoicePlanResult">
<include refid="selectOmsReceivableInvoicePlanVo"/>
where id = #{id}
</select>
<select id="selectOmsReceivableInvoicePlanList" parameterType="com.ruoyi.sip.domain.OmsReceivableInvoicePlan" resultMap="OmsReceivableInvoicePlanResult">
<include refid="selectOmsReceivableInvoicePlanVo"/>
<where>
<if test="receivableBillId != null "> and receivable_bill_id = #{receivableBillId}</if>
<if test="planInvoiceDate != null "> and plan_invoice_date = #{planInvoiceDate}</if>
<if test="planAmount != null "> and plan_amount = #{planAmount}</if>
<if test="planRate != null "> and plan_rate = #{planRate}</if>
<if test="remark != null and remark != ''"> and remark like concat('%', #{remark}, '%')</if>
</where>
</select>
<select id="firstUnPayPlan" resultType="com.ruoyi.sip.domain.OmsReceivableInvoicePlan">
select t1.id, t1.receivable_bill_id, t1.plan_invoice_date, t1.plan_amount, t1.plan_rate, t1.create_by, t1.create_time,
t1.update_time
from oms_receivable_invoice_plan t1
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}
order by t1.plan_invoice_date
limit 1
</select>
<insert id="insertOmsReceivableInvoicePlan" parameterType="com.ruoyi.sip.domain.OmsReceivableInvoicePlan" useGeneratedKeys="true" keyProperty="id">
insert into oms_receivable_invoice_plan
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="receivableBillId != null">receivable_bill_id,</if>
<if test="planInvoiceDate != null">plan_invoice_date,</if>
<if test="planAmount != null">plan_amount,</if>
<if test="planRate != null">plan_rate,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="createTime != null">create_time,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="updateBy != null and updateBy != ''">update_by,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="receivableBillId != null">#{receivableBillId},</if>
<if test="planInvoiceDate != null">#{planInvoiceDate},</if>
<if test="planAmount != null">#{planAmount},</if>
<if test="planRate != null">#{planRate},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="createTime != null">#{createTime},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="updateBy != null and updateBy != ''">#{updateBy},</if>
</trim>
</insert>
<update id="updateOmsReceivableInvoicePlan" parameterType="com.ruoyi.sip.domain.OmsReceivableInvoicePlan">
update oms_receivable_invoice_plan
<trim prefix="SET" suffixOverrides=",">
<if test="receivableBillId != null">receivable_bill_id = #{receivableBillId},</if>
<if test="planInvoiceDate != null">plan_invoice_date = #{planInvoiceDate},</if>
<if test="planAmount != null">plan_amount = #{planAmount},</if>
<if test="planRate != null">plan_rate = #{planRate},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteOmsReceivableInvoicePlanById" parameterType="Long">
delete from oms_receivable_invoice_plan where id = #{id}
</delete>
<delete id="deleteOmsReceivableInvoicePlanByIds" parameterType="String">
delete from oms_receivable_invoice_plan where id in
<foreach item="id" collection="ids.split(',')" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,129 @@
<?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.OmsReceivableReceiptDetailMapper">
<resultMap type="com.ruoyi.sip.domain.OmsReceivableReceiptDetail" id="OmsReceivableReceiptDetailResult">
<result property="id" column="id" />
<result property="receiptPlanId" column="receipt_plan_id" />
<result property="receivableBillId" column="receivable_bill_id" />
<result property="receiptTime" column="receipt_time" />
<result property="receiptAmount" column="receipt_amount" />
<result property="receiptRate" column="receipt_rate" />
<result property="receiptBillCode" column="receipt_bill_code" />
<result property="remark" column="remark" />
<result property="createTime" column="create_time" />
<result property="createBy" column="create_by" />
<result property="updateTime" column="update_time" />
<result property="updateBy" column="update_by" />
<result property="receivableDetailType" column="receivable_detail_type" />
</resultMap>
<sql id="selectOmsReceivableReceiptDetailVo">
select id, receipt_plan_id, receivable_bill_id, receipt_time, receipt_amount, receipt_rate, receipt_bill_code, remark, create_time, create_by, update_time, receivable_detail_type
from oms_receivable_receipt_detail
</sql>
<select id="selectOmsReceivableReceiptDetailById" parameterType="Long" resultMap="OmsReceivableReceiptDetailResult">
<include refid="selectOmsReceivableReceiptDetailVo"/>
where id = #{id}
</select>
<select id="selectOmsReceivableReceiptDetailList" parameterType="com.ruoyi.sip.domain.OmsReceivableReceiptDetail" resultMap="OmsReceivableReceiptDetailResult">
<include refid="selectOmsReceivableReceiptDetailVo"/>
<where>
<if test="receiptPlanId != null "> and receipt_plan_id = #{receiptPlanId}</if>
<if test="idList != null and idList.size>0 "> and id in <foreach collection="idList" separator="," close=")" open="(" item="item">#{item}</foreach></if>
<if test="receivableBillId != null "> and receivable_bill_id = #{receivableBillId}</if>
<if test="receiptTime != null "> and receipt_time = #{receiptTime}</if>
<if test="receiptAmount != null "> and receipt_amount = #{receiptAmount}</if>
<if test="receiptRate != null "> and receipt_rate = #{receiptRate}</if>
<if test="receiptBillCode != null and receiptBillCode != ''"> and receipt_bill_code = #{receiptBillCode}</if>
<if test="receivableDetailType != null and receivableDetailType != ''"> and receivable_detail_type = #{receivableDetailType}</if>
<if test="remark != null and remark != ''"> and remark like concat('%', #{remark}, '%')</if>
</where>
</select>
<select id="list" resultType="com.ruoyi.sip.domain.OmsReceivableReceiptDetail">
SELECT
t1.*,t2.receipt_bill_code,t2.actual_receipt_time,t2.receipt_status,t2.id as receipt_bill_id
FROM
oms_receivable_receipt_detail t1
LEFT JOIN oms_receipt_bill t2 ON t1.receipt_bill_code = t2.receipt_bill_code
</select>
<select id="selectByPaymentPlanIds" resultType="com.ruoyi.sip.domain.OmsReceivableReceiptDetail">
SELECT
t1.id, t1.receipt_plan_id, t1.receivable_bill_id, t1.receipt_time,
t1.receipt_amount, t1.receipt_rate, t1.receipt_bill_code, t1.remark,
t1.create_time, t1.create_by, t1.update_time, t1.receivable_detail_type
FROM
oms_receivable_receipt_detail t1
WHERE t1.receipt_plan_id IN
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item}
</foreach>
ORDER BY t1.create_time DESC
</select>
<insert id="insertOmsReceivableReceiptDetail" parameterType="com.ruoyi.sip.domain.OmsReceivableReceiptDetail" useGeneratedKeys="true" keyProperty="id">
insert into oms_receivable_receipt_detail
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="receiptPlanId != null">receipt_plan_id,</if>
<if test="receivableBillId != null">receivable_bill_id,</if>
<if test="receiptTime != null">receipt_time,</if>
<if test="receiptAmount != null">receipt_amount,</if>
<if test="receiptRate != null">receipt_rate,</if>
<if test="receiptBillCode != null and receiptBillCode != ''">receipt_bill_code,</if>
<if test="receivableDetailType != null and receivableDetailType != ''">receivable_detail_type,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="createTime != null">create_time,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="updateBy != null and updateBy != ''">update_by,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="receiptPlanId != null">#{receiptPlanId},</if>
<if test="receivableBillId != null">#{receivableBillId},</if>
<if test="receiptTime != null">#{receiptTime},</if>
<if test="receiptAmount != null">#{receiptAmount},</if>
<if test="receiptRate != null">#{receiptRate},</if>
<if test="receiptBillCode != null and receiptBillCode != ''">#{receiptBillCode},</if>
<if test="receivableDetailType != null and receivableDetailType != ''">#{receivableDetailType},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="createTime != null">#{createTime},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="updateBy != null and updateBy != ''">#{updateBy},</if>
</trim>
</insert>
<update id="updateOmsReceivableReceiptDetail" parameterType="com.ruoyi.sip.domain.OmsReceivableReceiptDetail">
update oms_receivable_receipt_detail
<trim prefix="SET" suffixOverrides=",">
<if test="receiptPlanId != null">receipt_plan_id = #{receiptPlanId},</if>
<if test="receivableBillId != null">receivable_bill_id = #{receivableBillId},</if>
<if test="receiptTime != null">receipt_time = #{receiptTime},</if>
<if test="receiptAmount != null">receipt_amount = #{receiptAmount},</if>
<if test="receiptRate != null">receipt_rate = #{receiptRate},</if>
<if test="receiptBillCode != null and receiptBillCode != ''">receipt_bill_code = #{receiptBillCode},</if>
<if test="receivableDetailType != null and receivableDetailType != ''">receivable_detail_type = #{receivableDetailType},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteOmsReceivableReceiptDetailById" parameterType="Long">
delete from oms_receivable_receipt_detail where id = #{id}
</delete>
<delete id="deleteOmsReceivableReceiptDetailByIds" parameterType="String">
delete from oms_receivable_receipt_detail where id in
<foreach item="id" collection="ids.split(',')" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,117 @@
<?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.OmsReceivableReceiptPlanMapper">
<resultMap type="com.ruoyi.sip.domain.OmsReceivableReceiptPlan" id="OmsReceivableReceiptPlanResult">
<result property="id" column="id" />
<result property="receivableBillId" column="receivable_bill_id" />
<result property="planReceiptDate" column="plan_receipt_date" />
<result property="planAmount" column="plan_amount" />
<result property="planRate" column="plan_rate" />
<result property="remark" column="remark" />
<result property="createTime" column="create_time" />
<result property="createBy" column="create_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectOmsReceivableReceiptPlanVo">
select id, receivable_bill_id, plan_receipt_date, plan_amount, plan_rate, remark, create_time, create_by, update_time
from oms_receivable_receipt_plan
</sql>
<select id="selectOmsReceivableReceiptPlanById" parameterType="Long" resultMap="OmsReceivableReceiptPlanResult">
<include refid="selectOmsReceivableReceiptPlanVo"/>
where id = #{id}
</select>
<select id="selectOmsReceivableReceiptPlanList" parameterType="com.ruoyi.sip.domain.OmsReceivableReceiptPlan" resultMap="OmsReceivableReceiptPlanResult">
<include refid="selectOmsReceivableReceiptPlanVo"/>
<where>
<if test="receivableBillId != null "> and receivable_bill_id = #{receivableBillId}</if>
<if test="planReceiptDate != null "> and plan_receipt_date = #{planReceiptDate}</if>
<if test="planAmount != null "> and plan_amount = #{planAmount}</if>
<if test="planRate != null "> and plan_rate = #{planRate}</if>
<if test="remark != null and remark != ''"> and remark like concat('%', #{remark}, '%')</if>
</where>
</select>
<select id="selectOmsReceivableReceiptPlanListByReceivableBillId" parameterType="Long" resultMap="OmsReceivableReceiptPlanResult">
<include refid="selectOmsReceivableReceiptPlanVo"/>
where receivable_bill_id = #{receivableBillId}
order by plan_receipt_date
</select>
<select id="firstUnPayPlan" resultType="com.ruoyi.sip.domain.OmsReceivableReceiptPlan">
select t1.id,
t1.receivable_bill_id,
t1.plan_receipt_date,
t1.plan_amount,
t1.plan_rate,
t1.remark,
t1.create_time,
t1.create_by,
t1.update_time
from oms_receivable_receipt_plan t1
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}
order by plan_receipt_date
limit 1
</select>
<insert id="insertOmsReceivableReceiptPlan" parameterType="com.ruoyi.sip.domain.OmsReceivableReceiptPlan" useGeneratedKeys="true" keyProperty="id">
insert into oms_receivable_receipt_plan
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="receivableBillId != null">receivable_bill_id,</if>
<if test="planReceiptDate != null">plan_receipt_date,</if>
<if test="planAmount != null">plan_amount,</if>
<if test="planRate != null">plan_rate,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="createTime != null">create_time,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="receivableBillId != null">#{receivableBillId},</if>
<if test="planReceiptDate != null">#{planReceiptDate},</if>
<if test="planAmount != null">#{planAmount},</if>
<if test="planRate != null">#{planRate},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="createTime != null">#{createTime},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateOmsReceivableReceiptPlan" parameterType="com.ruoyi.sip.domain.OmsReceivableReceiptPlan">
update oms_receivable_receipt_plan
<trim prefix="SET" suffixOverrides=",">
<if test="receivableBillId != null">receivable_bill_id = #{receivableBillId},</if>
<if test="planReceiptDate != null">plan_receipt_date = #{planReceiptDate},</if>
<if test="planAmount != null">plan_amount = #{planAmount},</if>
<if test="planRate != null">plan_rate = #{planRate},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteOmsReceivableReceiptPlanById" parameterType="Long">
delete from oms_receivable_receipt_plan where id = #{id}
</delete>
<delete id="deleteOmsReceivableReceiptPlanByIds" parameterType="String">
delete from oms_receivable_receipt_plan where id in
<foreach item="id" collection="ids.split(',')" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<delete id="deleteByReceivableBillId" parameterType="Long">
delete from oms_receivable_receipt_plan where receivable_bill_id = #{receivableBillId}
</delete>
</mapper>