feat(finance): 新增收票单管理功能
- 新增收票单新增、详情查看、附件上传、退回及红冲申请功能 - 实现收票单与应付单关联展示及合并收票逻辑 - 提供收票计划选择与金额计算功能 - 支持收票状态、审批状态等多维度查询过滤 - 集成字典标签展示收票类型、审批状态等相关字段 - 添加收票单据的增删改查接口支持dev_1.0.0
parent
ed9fda7fe3
commit
4cc2d3beb1
|
|
@ -0,0 +1,362 @@
|
|||
<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="ticketBillType">
|
||||
<el-select disabled v-model="form.ticketBillType" placeholder="请选择收票单类型" clearable>
|
||||
<el-option
|
||||
v-for="dict in dict.type.payment_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.vendorName" readonly/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预计收票时间" prop="ticketTime">
|
||||
<el-date-picker
|
||||
v-model="form.ticketTime"
|
||||
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="payableOrdersWithPlans" border max-height="300px" style="margin-bottom: 20px;">
|
||||
<el-table-column label="应付单编号" align="center" prop="payableBillCode" width="150"/>
|
||||
<el-table-column label="预计收票时间" align="center" prop="estimatedPaymentTime" width="180"/>
|
||||
<el-table-column label="收票计划" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.ticketPlans ? scope.row.ticketPlans.length : 0 }} 条计划</span>
|
||||
</template>
|
||||
</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="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">
|
||||
{{ calculateOrderCurrentTicketAmount(scope.row.id).toFixed(2) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="本次收票比例" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
{{ calculateOrderCurrentTicketRate(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="handleOpenTicketPlanSelector(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.div(totalPlannedAmount,totalPayableAmountWithTax,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="isTicketPlanSelectorOpen" width="70%"
|
||||
@close="isTicketPlanSelectorOpen=false" append-to-body>
|
||||
<receiving-ticket-plan
|
||||
ref="planSelector"
|
||||
:payable-data="choosePayable"
|
||||
:selected-plans="choosePayable.ticketPlans"
|
||||
@confirm="handleTicketPlanConfirm"
|
||||
/>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="isTicketPlanSelectorOpen=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 ReceivingTicketPlan from './ReceivingTicketPlan.vue';
|
||||
import {getReceivingTicketPlan} from "@/api/finance/payable";
|
||||
|
||||
export default {
|
||||
name: "MergeReceiptDialog",
|
||||
components: {ReceivingTicketPlan},
|
||||
dicts: ['invoice_status','payment_bill_type'], // Add dicts for dict-tag
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
payableOrders: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
internalVisible: this.visible,
|
||||
planTitle: '',
|
||||
choosePayable: {},
|
||||
form: {
|
||||
ticketBillType: 'FROM_PAYABLE', // Default to a type, or make it dynamic
|
||||
vendorName: '',
|
||||
ticketTime: null,
|
||||
},
|
||||
payableOrdersWithPlans: [], // Each order will now have its own ticketPlans array
|
||||
isTicketPlanSelectorOpen: false,
|
||||
currentPayableOrderIndexForPlan: -1, // Index of the order in payableOrdersWithPlans
|
||||
loadingTicketPlans: false, // Loading state for fetching ticket plans
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.internalVisible;
|
||||
},
|
||||
set(val) {
|
||||
this.internalVisible = val;
|
||||
this.$emit('update:visible', val);
|
||||
}
|
||||
},
|
||||
totalPayableAmountWithTax() {
|
||||
return this.payableOrdersWithPlans.reduce((sum, order) => sum + (order.totalPriceWithTax || 0), 0);
|
||||
},
|
||||
totalPlannedAmount() {
|
||||
return this.payableOrdersWithPlans.reduce((orderSum, order) => {
|
||||
const orderPlansTotal = (order.ticketPlans || []).reduce((planSum, plan) => planSum + (plan.planAmount || 0), 0);
|
||||
return orderSum + orderPlansTotal;
|
||||
}, 0);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
visible(newVal) {
|
||||
this.internalVisible = newVal;
|
||||
if (newVal) {
|
||||
this.initDialogData();
|
||||
}
|
||||
},
|
||||
payableOrders: {
|
||||
handler(newVal) {
|
||||
if (this.dialogVisible) {
|
||||
this.initDialogData();
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initDialogData() {
|
||||
// Initialize form fields
|
||||
if (this.payableOrders.length > 0) {
|
||||
const firstVendorName = this.payableOrders[0].vendorName;
|
||||
const allSameVendor = this.payableOrders.every(order => order.vendorName === firstVendorName);
|
||||
this.form.vendorName = allSameVendor ? firstVendorName : '多个制造商';
|
||||
this.form.ticketTime = null; // Reset time
|
||||
} else {
|
||||
this.form.vendorName = '';
|
||||
this.form.ticketTime = null;
|
||||
}
|
||||
this.form.ticketBillType = 'FROM_PAYABLE'; // Default
|
||||
|
||||
// Initialize payableOrdersWithPlans
|
||||
this.payableOrdersWithPlans = this.payableOrders.map(order => ({
|
||||
...order,
|
||||
ticketPlans: order.ticketPlans || [], // 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.$refs.planSelector.selectedPlan) {
|
||||
this.$modal.msgError('无法获取计划选择器组件或其选择的计划');
|
||||
return;
|
||||
}
|
||||
const selectedPlans = this.$refs.planSelector.selectedPlan;
|
||||
|
||||
const orderIndex = this.payableOrdersWithPlans.findIndex(o => o.id === this.choosePayable.id);
|
||||
if (orderIndex === -1) {
|
||||
this.$modal.msgError('找不到要更新的应付单');
|
||||
return;
|
||||
}
|
||||
|
||||
const currentOrder = this.payableOrdersWithPlans[orderIndex];
|
||||
|
||||
// Ensure the ticketPlans array exists
|
||||
if (!currentOrder.ticketPlans) {
|
||||
this.$set(currentOrder, 'ticketPlans', []);
|
||||
}
|
||||
|
||||
// Add new plans, checking for duplicates by plan ID
|
||||
let addedCount = 0;
|
||||
selectedPlans.forEach(newPlan => {
|
||||
const existingPlan = currentOrder.ticketPlans.find(p => p.id === newPlan.id);
|
||||
if (!existingPlan) {
|
||||
currentOrder.ticketPlans.push(newPlan);
|
||||
addedCount++;
|
||||
}
|
||||
});
|
||||
|
||||
this.isTicketPlanSelectorOpen = false;
|
||||
if (addedCount > 0) {
|
||||
this.$modal.msgSuccess(`成功补充 ${addedCount} 条收票计划`);
|
||||
} else {
|
||||
this.$modal.msgWarning('没有新的收票计划被添加');
|
||||
}
|
||||
},
|
||||
handleConfirm() {
|
||||
// Validate main form fields
|
||||
if (!this.form.ticketBillType) {
|
||||
this.$modal.msgError('请选择收票单类型');
|
||||
return;
|
||||
}
|
||||
if (!this.form.ticketTime) {
|
||||
this.$modal.msgError('请选择预计收票时间');
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate each payable order's ticket plans
|
||||
for (const order of this.payableOrdersWithPlans) {
|
||||
if (!order.ticketPlans || order.ticketPlans.length === 0) {
|
||||
this.$modal.msgError(`应付单 ${order.payableBillCode} 至少需要一条收票计划`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (const plan of order.ticketPlans) {
|
||||
if (!plan.planTicketDate) {
|
||||
this.$modal.msgError(`应付单 ${order.payableBillCode} 的收票计划中预计收票时间不能为空。`);
|
||||
return;
|
||||
}
|
||||
if (plan.planAmount === null || plan.planAmount === undefined || plan.planAmount <= 0) {
|
||||
this.$modal.msgError(`应付单 ${order.payableBillCode} 的收票计划中预计收票金额必须大于0。`);
|
||||
return;
|
||||
}
|
||||
if (plan.planRate === null || plan.planRate === undefined) {
|
||||
this.$modal.msgError(`应付单 ${order.payableBillCode} 的收票计划中收票比例不能为空。`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct the final data to be emitted to the parent
|
||||
const mergedReceiptData = {
|
||||
ticketBillType: this.form.ticketBillType,
|
||||
ticketTime: this.form.ticketTime,
|
||||
// Collect all payable orders with their updated ticket plans
|
||||
payableOrders: this.payableOrdersWithPlans.map(order => ({
|
||||
id: order.id,
|
||||
payableBillCode: order.payableBillCode,
|
||||
ticketPlans: order.ticketPlans.map(plan => ({
|
||||
planTicketDate: plan.planTicketDate,
|
||||
planAmount: plan.planAmount,
|
||||
planRate: plan.planRate,
|
||||
remark: plan.remark,
|
||||
id: plan.id,
|
||||
})),
|
||||
})),
|
||||
totalMergeTicketAmount: this.totalPlannedAmount, // Total amount for the merged bill
|
||||
};
|
||||
|
||||
this.$emit('confirm', mergedReceiptData);
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
handleCancel() {
|
||||
this.dialogVisible = false;
|
||||
this.resetForm();
|
||||
},
|
||||
resetForm() {
|
||||
this.form = {
|
||||
ticketBillType: 'FROM_PAYABLE',
|
||||
vendorName: '',
|
||||
ticketTime: null,
|
||||
};
|
||||
this.payableOrdersWithPlans = [];
|
||||
|
||||
this.currentPayableOrderIndexForPlan = -1;
|
||||
this.loadingTicketPlans = false;
|
||||
},
|
||||
handleOpenTicketPlanSelector(row, index) {
|
||||
this.planTitle = `选择收票计划 - ${row.payableBillCode}`;
|
||||
this.choosePayable = row;
|
||||
this.currentPayableOrderIndexForPlan = index;
|
||||
this.isTicketPlanSelectorOpen = true;
|
||||
console.log(this.choosePayable.id)
|
||||
},
|
||||
handleTicketPlanConfirm(updatedPlans) {
|
||||
// Update the ticket plans for the specific order
|
||||
if (this.currentPayableOrderIndexForPlan !== -1) {
|
||||
this.$set(this.payableOrdersWithPlans[this.currentPayableOrderIndexForPlan], 'ticketPlans', updatedPlans);
|
||||
}
|
||||
this.isTicketPlanSelectorOpen = false;
|
||||
this.currentPayableOrderIndexForPlan = -1;
|
||||
},
|
||||
calculateOrderCurrentTicketAmount(orderId) {
|
||||
const order = this.payableOrdersWithPlans.find(o => o.id === orderId);
|
||||
if (order && order.ticketPlans) {
|
||||
return order.ticketPlans.reduce((sum, plan) => sum + (plan.planAmount || 0), 0);
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
calculateOrderCurrentTicketRate(orderId) {
|
||||
const order = this.payableOrdersWithPlans.find(o => o.id === orderId);
|
||||
if (order && order.ticketPlans && order.unInvoicedAmount >= 0) {
|
||||
const currentAmount = this.calculateOrderCurrentTicketAmount(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>
|
||||
|
|
@ -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="handleSaveTicketPlan"
|
||||
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="ticketPlans" border @selection-change="selectPlan" ref="ticketPlanTable">
|
||||
<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.planTicketDate" 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="handleAddTicketPlanRow"
|
||||
>增加下行
|
||||
</el-button>
|
||||
<el-button v-if="isEditing && !isNumberStr(scope.row.detailId)"
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDeleteTicketPlanRow(scope.$index)"
|
||||
:disabled="ticketPlans.length === 1 || scope.row.status === 'received'"
|
||||
>删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getReceivingTicketPlan, updateReceivingTicketPlan} from "@/api/finance/payable";
|
||||
import {isNumberStr} from "@/utils";
|
||||
|
||||
export default {
|
||||
name: "ReceivingTicketPlan",
|
||||
props: {
|
||||
payableData: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
}
|
||||
},
|
||||
isInitEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
selectedPlans: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedPlan:[],
|
||||
isEditing: false,
|
||||
loading: false,
|
||||
ticketPlans: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return `选择收票计划 - ${this.payableData.payableBillCode}`;
|
||||
},
|
||||
totalPlannedAmount() {
|
||||
return this.ticketPlans.reduce((sum, plan) => sum + (plan.planAmount || 0), 0);
|
||||
},
|
||||
totalUnpaidAmount() {
|
||||
return this.payableData.unInvoicedAmount || 0;
|
||||
},
|
||||
totalPriceWithTax() {
|
||||
return this.payableData.totalPriceWithTax || 0;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'payableData.id': {
|
||||
handler(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
this.fetchTicketPlans(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
|
||||
},
|
||||
fetchTicketPlans(payableId) {
|
||||
if (this.payableData && payableId) {
|
||||
getReceivingTicketPlan(payableId).then(response => {
|
||||
this.ticketPlans = response.data.map(item => ({
|
||||
...item,
|
||||
status: item.status || 'pending'
|
||||
}));
|
||||
if (this.ticketPlans.length === 0) {
|
||||
this.initDefaultTicketPlan();
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.ticketPlans.forEach(plan => {
|
||||
const isSelected = this.selectedPlans.some(selected => selected.id === plan.id);
|
||||
if (isSelected) {
|
||||
this.$refs.ticketPlanTable.toggleRowSelection(plan, true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.initDefaultTicketPlan();
|
||||
|
||||
}
|
||||
},
|
||||
initDefaultTicketPlan() {
|
||||
this.ticketPlans = [{
|
||||
planTicketDate: null,
|
||||
planAmount: this.totalPriceWithTax,
|
||||
planRate: 100,
|
||||
remark: '',
|
||||
status: 'pending'
|
||||
}];
|
||||
},
|
||||
handleSaveTicketPlan() {
|
||||
if (!this.validateTicketPlans()) {
|
||||
return;
|
||||
}
|
||||
if (!this.validateTicketPlanTotals()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.ticketPlans.length; i++) {
|
||||
const plan = this.ticketPlans[i];
|
||||
if (!plan.planTicketDate) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
updateReceivingTicketPlan(this.payableData.id, this.ticketPlans).then(() => {
|
||||
this.$modal.msgSuccess("保存成功");
|
||||
this.fetchTicketPlans(this.payableData.id);
|
||||
});
|
||||
},
|
||||
|
||||
handleAddTicketPlanRow() {
|
||||
this.ticketPlans.push({
|
||||
planTicketDate: null,
|
||||
planAmount: 0,
|
||||
planRate: 0,
|
||||
remark: '',
|
||||
status: 'pending'
|
||||
});
|
||||
},
|
||||
handleDeleteTicketPlanRow(index) {
|
||||
if (this.ticketPlans.length === 1) {
|
||||
this.$modal.msgError("至少需要保留一条收票计划。");
|
||||
return;
|
||||
}
|
||||
if (this.ticketPlans[index].status === 'received') {
|
||||
this.$modal.msgError("已收票的计划不能删除。");
|
||||
return;
|
||||
}
|
||||
this.ticketPlans.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);
|
||||
},
|
||||
validateTicketPlanTotals() {
|
||||
const totalAmount = this.ticketPlans.reduce((sum, plan) => sum + (plan.planAmount || 0), 0);
|
||||
|
||||
if (totalAmount !== this.totalPriceWithTax) {
|
||||
this.$modal.msgError(`预计收票金额之和应该等于应付总金额[${this.totalPriceWithTax}]`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
validateTicketPlans() {
|
||||
if (this.ticketPlans.length === 0) {
|
||||
this.$modal.msgError("请至少添加一条收票计划。");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.ticketPlans.length; i++) {
|
||||
const plan = this.ticketPlans[i];
|
||||
if (!plan.planTicketDate) {
|
||||
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>
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
<template>
|
||||
<el-dialog title="新增收票单" :visible.sync="internalVisible" width="500px" @close="handleClose">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
||||
<el-form-item label="收票单类型" prop="receiptBillType">
|
||||
<el-select v-model="form.receiptBillType" disabled placeholder="请选择收票单类型">
|
||||
<el-option
|
||||
v-for="dict in dicts.receipt_bill_type"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="制造商名称" prop="vendorCode">
|
||||
<el-select v-model="form.vendorCode" placeholder="请选择制造商" style="width:100%" >
|
||||
<el-option v-for="item in vendorOptions" :key="item.vendorCode" :label="item.vendorName" :value="item.vendorCode"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="预计收票时间" prop="receiptTime">
|
||||
<el-date-picker
|
||||
v-model="form.receiptTime"
|
||||
type="datetime"
|
||||
placeholder="选择日期"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="含税总价" prop="totalPriceWithTax">
|
||||
<el-input-number v-model="form.totalPriceWithTax" @change="handlePriceChange" :precision="2"
|
||||
:step="1"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="税率" prop="taxRate">
|
||||
<el-input-number v-model="form.taxRate" @change="handlePriceChange" :precision="2" :step="0.01"
|
||||
:max="1"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="未税总价" prop="totalPriceWithoutTax">
|
||||
<el-input v-model="form.totalPriceWithoutTax" :disabled="true"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="税额" prop="taxAmount">
|
||||
<el-input v-model="form.taxAmount" :disabled="true"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleClose">取 消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {listAllVendor} from "@/api/base/vendor";
|
||||
|
||||
export default {
|
||||
name: "AddForm",
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
dicts: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
internalVisible: this.visible,
|
||||
vendorOptions: [],
|
||||
form: {
|
||||
receiptBillType:'STANDARD_INVOICE', // Default type, assuming STANDARD_INVOICE exists or user changes it
|
||||
vendorName: null,
|
||||
receiptTime: null,
|
||||
totalPriceWithTax: 0,
|
||||
taxRate: 0.13, // Default tax rate
|
||||
totalPriceWithoutTax: 0,
|
||||
taxAmount: 0
|
||||
},
|
||||
rules: {
|
||||
receiptBillType: [{required: true, message: "收票单类型不能为空", trigger: "change"}],
|
||||
vendorName: [{required: true, message: "制造商名称不能为空", trigger: "blur"}],
|
||||
receiptTime: [{required: true, message: "预计收票时间不能为空", trigger: "change"}],
|
||||
totalPriceWithTax: [{required: true, message: "含税总价不能为空", trigger: "blur"}]
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
visible(newVal) {
|
||||
this.internalVisible = newVal;
|
||||
if (newVal) {
|
||||
this.resetForm();
|
||||
this.getVendorList();
|
||||
|
||||
}
|
||||
},
|
||||
internalVisible(newVal) {
|
||||
this.$emit("update:visible", newVal);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 获取厂商列表 */
|
||||
getVendorList() {
|
||||
return listAllVendor().then(res => {
|
||||
this.vendorOptions = res.data;
|
||||
})
|
||||
},
|
||||
handlePriceChange() {
|
||||
const taxed = this.form.totalPriceWithTax || 0;
|
||||
const rate = this.form.taxRate || 0;
|
||||
|
||||
const unTaxed = this.$calc.div(taxed, this.$calc.add(1, rate));
|
||||
const taxAmount = this.$calc.sub(taxed, unTaxed);
|
||||
|
||||
this.form.totalPriceWithoutTax = unTaxed;
|
||||
this.form.taxAmount = taxAmount;
|
||||
},
|
||||
handleClose() {
|
||||
this.internalVisible = false;
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate(valid => {
|
||||
if (valid) {
|
||||
this.$emit("submit", this.form);
|
||||
}
|
||||
});
|
||||
},
|
||||
resetForm() {
|
||||
if (this.$refs.form) {
|
||||
this.$refs.form.resetFields();
|
||||
}
|
||||
this.form = {
|
||||
receiptBillType: 'STANDARD_INVOICE',
|
||||
vendorName: null,
|
||||
receiptTime: null,
|
||||
totalPriceWithTax: 0,
|
||||
taxRate: 0.13,
|
||||
totalPriceWithoutTax: 0,
|
||||
taxAmount: 0
|
||||
};
|
||||
this.handlePriceChange();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
<template>
|
||||
<el-drawer
|
||||
title="收票单详情"
|
||||
:visible.sync="visible"
|
||||
direction="rtl"
|
||||
size="70%"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div class="dialog-body" v-if="detail">
|
||||
<div class="section">
|
||||
<el-divider content-position="left">采购-收票单</el-divider>
|
||||
<div class="details-container">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">采购-收票单编号: {{ detail.ticketBillCode }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">预计收票时间: {{ detail.ticketTime }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">制造商开票时间: {{ detail.vendorTicketTime }}</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">制造商名称: {{ detail.vendorName }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">含税总价: {{ detail.totalPriceWithTax }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">未税总价: {{ detail.totalPriceWithoutTax }}</div>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">税额: {{ detail.taxAmount }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">发票含税总价: {{ detail.actualReceiptTime || '-'}}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">发票未税总价: {{ detail.actualReceiptTime || '-'}}</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">发票税额: {{ detail.taxAmount }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">收票状态:
|
||||
<dict-tag :options="dict.type.receipt_status" :value="detail.ticketStatus"/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">备注: {{ detail.remark }}</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">审批节点: {{ detail.approveNode|| '-' }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">审批状态:
|
||||
<dict-tag :options="dict.type.approve_status" :value="detail.approveStatus"/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">审批通过时间: {{ detail.approveTime || '-'}}</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<el-divider content-position="left">采购-应付单</el-divider>
|
||||
<el-table :data="detail.detailList">
|
||||
<el-table-column type="index" label="序号" width="50"></el-table-column>
|
||||
<el-table-column property="projectCode" label="项目编号"></el-table-column>
|
||||
<el-table-column property="projectName" label="项目名称"></el-table-column>
|
||||
<el-table-column property="payableBillCode" label="采购应付单编号"></el-table-column>
|
||||
<el-table-column property="totalPriceWithTax" label="含税总价"></el-table-column>
|
||||
<el-table-column property="paymentAmount" label="本次收票金额"></el-table-column>
|
||||
<el-table-column property="paymentRate" label="本次收票比例(%)"></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "DetailDrawer",
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
detail: {
|
||||
type: Object,
|
||||
default: () => null,
|
||||
},
|
||||
},
|
||||
dicts:['receipt_bill_type','approve_status','receipt_status'],
|
||||
methods: {
|
||||
handleClose() {
|
||||
this.$emit("update:visible", false);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dialog-body {
|
||||
max-height: calc(100vh - 50px);
|
||||
overflow-y: auto;
|
||||
padding: 0 20px 20px 20px;
|
||||
}
|
||||
|
||||
.details-container {
|
||||
border: 1px solid #EBEEF5;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
border: 1px solid #EBEEF5;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,572 @@
|
|||
<template>
|
||||
<el-dialog :title="titleText" :visible.sync="dialogVisible" width="900px" @close="handleClose">
|
||||
<div v-if="loading" class="loading-spinner">
|
||||
<i class="el-icon-loading"></i>
|
||||
</div>
|
||||
<div v-else class="receipt-dialog-body">
|
||||
<div v-if="canUpload" class="upload-btn-container">
|
||||
<el-button type="primary" icon="el-icon-upload" @click="openUploadDialog">上传{{ titleText }}</el-button>
|
||||
</div>
|
||||
|
||||
<el-timeline v-if="attachments.length > 0">
|
||||
<el-timeline-item
|
||||
v-for="attachment in attachments"
|
||||
:key="attachment.id"
|
||||
:timestamp="parseTime(attachment.createTime, '{y}-{m}-{d} {h}:{i}:{s}')"
|
||||
placement="top"
|
||||
>
|
||||
<el-card>
|
||||
<div class="receipt-card-content">
|
||||
<div class="receipt-details">
|
||||
<div class="detail-item">
|
||||
<span class="item-label">票据类型</span>
|
||||
<span class="item-value"><dict-tag :options="dict.type.finance_invoice_type" :value="attachment.ticketType"/></span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="item-label">{{ titleText }}</span>
|
||||
<div class="item-value">
|
||||
<div class="image-wrapper">
|
||||
<el-image
|
||||
v-if="!isPdf(attachment.filePath)"
|
||||
:src="getImageUrl(attachment.filePath)"
|
||||
:preview-src-list="previewList"
|
||||
style="width: 200px; height: 150px;"
|
||||
fit="contain"
|
||||
></el-image>
|
||||
<div v-else-if="pdfUrls[attachment.filePath]" class="pdf-thumbnail-container" @click="openPdfPreview(pdfUrls[attachment.filePath])">
|
||||
<iframe :src="pdfUrls[attachment.filePath]" width="100%" height="150px" frameborder="0"></iframe>
|
||||
<div class="pdf-hover-overlay">
|
||||
<i class="el-icon-zoom-in"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="attachment.delFlag === '2'" class="void-overlay">作废</div>
|
||||
</div>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="primary"
|
||||
class="download-btn"
|
||||
icon="el-icon-download"
|
||||
@click="downloadFile(attachment)"
|
||||
>下载{{ titleText }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-item">
|
||||
<span class="item-label">含税金额</span>
|
||||
<span class="item-value">{{ receiptData.totalPriceWithTax }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="item-label">发票含税金额</span>
|
||||
<span class="item-value">{{ receiptData.ticketPriceWithTax }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="item-label">未税金额</span>
|
||||
<span class="item-value">{{ receiptData.totalPriceWithoutTax }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="item-label">发票未税金额</span>
|
||||
<span class="item-value">{{ receiptData.ticketPriceWithoutTax }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="item-label">税额</span>
|
||||
<span class="item-value">{{ receiptData.taxAmount }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="item-label">发票税额</span>
|
||||
<span class="item-value">{{ receiptData.ticketAmount }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="item-label">备注</span>
|
||||
<span class="item-value">{{ attachment.remark }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
<el-empty v-else :description="'暂无' + titleText"></el-empty>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">关闭</el-button>
|
||||
</span>
|
||||
|
||||
<!-- PDF Preview Dialog -->
|
||||
<el-dialog
|
||||
:visible.sync="pdfPreviewVisible"
|
||||
width="80%"
|
||||
top="5vh"
|
||||
append-to-body
|
||||
custom-class="pdf-preview-dialog"
|
||||
>
|
||||
<iframe :src="currentPdfUrl" width="100%" height="600px" frameborder="0"></iframe>
|
||||
</el-dialog>
|
||||
|
||||
<!-- Upload Dialog -->
|
||||
<el-dialog
|
||||
:title="'上传' + titleText"
|
||||
:visible.sync="uploadDialogVisible"
|
||||
width="70vw"
|
||||
append-to-body
|
||||
@close="closeUploadDialog"
|
||||
custom-class="upload-receipt-dialog"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form :model="uploadForm" ref="uploadForm" :rules="rules" label-width="120px" size="medium" >
|
||||
<el-form-item label="票据类型" prop="ticketType" required>
|
||||
<el-select v-model="uploadForm.ticketType" placeholder="请输入发票含税总价">
|
||||
<el-option
|
||||
v-for="item in dict.type.finance_invoice_type"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="收票附件" prop="file" required>
|
||||
<div style="display: flex; flex-direction: column; align-items: flex-start;">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
action="#"
|
||||
:auto-upload="false"
|
||||
:on-change="handleFileChange"
|
||||
:on-remove="handleFileRemove"
|
||||
:show-file-list="false"
|
||||
accept=".jpg,.jpeg,.png,.pdf"
|
||||
>
|
||||
<el-button size="small" type="primary" icon="el-icon-upload2">{{ uploadForm.file ? '重新上传' : '点击上传' }}</el-button>
|
||||
</el-upload>
|
||||
<div class="el-upload__tip" style="line-height: 1.5; margin-top: 5px;">支持上传PNG、JPG、PDF文件格式</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="含税总价">
|
||||
<span>{{ receiptData.totalPriceWithTax }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="发票含税总价" prop="ticketPriceWithTax" required>
|
||||
<el-input v-model="uploadForm.ticketPriceWithTax" placeholder="请输入发票含税总价"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="未税总价">
|
||||
<span>{{ receiptData.totalPriceWithoutTax }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="发票未税总价" prop="ticketPriceWithoutTax" required>
|
||||
<el-input v-model="uploadForm.ticketPriceWithoutTax" placeholder="请输入发票未税总价"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="税额">
|
||||
<span>{{ receiptData.taxAmount }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="发票税额" prop="ticketAmount" required>
|
||||
<el-input v-model="uploadForm.ticketAmount" placeholder="请输入发票税额"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="uploadForm.remark"
|
||||
:rows="4"
|
||||
placeholder="此处备注描述..."
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="upload-preview-container" style="height: 70vh;">
|
||||
<div v-if="previewUrl" class="preview-content">
|
||||
<img v-if="!isPreviewPdf" :src="previewUrl" class="preview-image" />
|
||||
<iframe v-else :src="previewUrl" width="100%" height="100%" frameborder="0"></iframe>
|
||||
</div>
|
||||
<div v-else class="preview-placeholder">
|
||||
<div class="placeholder-icon">
|
||||
<i class="el-icon-picture"></i>
|
||||
</div>
|
||||
<div class="placeholder-text">点击图片进入预览</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitNewUpload">保存</el-button>
|
||||
<el-button @click="closeUploadDialog">取消</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
|
||||
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getReceiptAttachments, uploadReceiptAttachment } from "@/api/finance/receipt";
|
||||
import request from '@/utils/request';
|
||||
|
||||
export default {
|
||||
name: "ReceiptDialog",
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
receiptData: {
|
||||
type: Object,
|
||||
default: () => null,
|
||||
},
|
||||
dicts: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
dicts:['finance_invoice_type'],
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
attachments: [],
|
||||
// Upload Dialog Data
|
||||
uploadDialogVisible: false,
|
||||
uploadForm: {
|
||||
totalPriceWithTax: '',
|
||||
ticketPriceWithTax: '',
|
||||
totalPriceWithoutTax: '',
|
||||
ticketPriceWithoutTax: '',
|
||||
taxAmount: '',
|
||||
ticketType: '',
|
||||
remark: '',
|
||||
file: null
|
||||
},
|
||||
rules: {
|
||||
ticketPriceWithTax: [
|
||||
{ required: true, message: "请输入发票含税总价", trigger: "blur" }
|
||||
],
|
||||
ticketPriceWithoutTax: [
|
||||
{ required: true, message: "请输入发票未税总价", trigger: "blur" }
|
||||
],
|
||||
ticketAmount: [
|
||||
{ required: true, message: "请输入发票税额", trigger: "blur" }
|
||||
]
|
||||
},
|
||||
previewUrl: '',
|
||||
isPreviewPdf: false,
|
||||
// PDF Preview Data
|
||||
pdfUrls: {},
|
||||
pdfPreviewVisible: false,
|
||||
currentPdfUrl: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.visible;
|
||||
},
|
||||
set(val) {
|
||||
this.$emit("update:visible", val);
|
||||
},
|
||||
},
|
||||
previewList() {
|
||||
return this.attachments
|
||||
.filter(att => !this.isPdf(att.filePath))
|
||||
.map(att => this.getImageUrl(att.filePath));
|
||||
},
|
||||
canUpload() {
|
||||
if (!this.attachments || this.attachments.length === 0) {
|
||||
return true;
|
||||
}
|
||||
return this.attachments.every(att => att.delFlag === '2');
|
||||
},
|
||||
titleText() {
|
||||
return '发票';
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
if (val && this.receiptData) {
|
||||
this.fetchAttachments();
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
fetchAttachments() {
|
||||
if (!this.receiptData.id) return;
|
||||
this.loading = true;
|
||||
getReceiptAttachments(this.receiptData.id, { type: 'ticket' })
|
||||
.then(response => {
|
||||
const data = response.data || [];
|
||||
data.sort((a, b) => new Date(b.createTime) - new Date(a.createTime));
|
||||
this.attachments = data;
|
||||
this.loadPdfPreviews();
|
||||
this.loading = false;
|
||||
})
|
||||
.catch(() => {
|
||||
this.attachments = [];
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
loadPdfPreviews() {
|
||||
this.attachments.forEach(att => {
|
||||
if (this.isPdf(att.filePath) && !this.pdfUrls[att.filePath]) {
|
||||
request({
|
||||
url: '/common/download/resource',
|
||||
method: 'get',
|
||||
params: { resource: att.filePath },
|
||||
responseType: 'blob'
|
||||
}).then(res => {
|
||||
const blob = new Blob([res.data], { type: 'application/pdf' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
this.$set(this.pdfUrls, att.filePath, url);
|
||||
}).catch(console.error);
|
||||
}
|
||||
});
|
||||
},
|
||||
openPdfPreview(url) {
|
||||
if (!url) return;
|
||||
this.currentPdfUrl = url;
|
||||
this.pdfPreviewVisible = true;
|
||||
},
|
||||
getImageUrl(resource) {
|
||||
return process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" + resource;
|
||||
},
|
||||
isPdf(filePath) {
|
||||
return filePath && filePath.toLowerCase().endsWith('.pdf');
|
||||
},
|
||||
downloadFile(attachment) {
|
||||
const link = document.createElement('a');
|
||||
link.href = this.getImageUrl(attachment.filePath);
|
||||
link.download = attachment.fileName || 'receipt';
|
||||
link.style.display = 'none';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
},
|
||||
handleClose() {
|
||||
this.attachments = [];
|
||||
// Clean up object URLs
|
||||
Object.values(this.pdfUrls).forEach(url => URL.revokeObjectURL(url));
|
||||
this.pdfUrls = {};
|
||||
},
|
||||
// New Upload Dialog Methods
|
||||
openUploadDialog() {
|
||||
this.uploadForm = {
|
||||
totalPriceWithTax: '',
|
||||
totalPriceWithoutTax: '',
|
||||
taxAmount: '',
|
||||
remark: '',
|
||||
file: null
|
||||
};
|
||||
if (this.$refs.uploadForm) {
|
||||
this.$refs.uploadForm.clearValidate();
|
||||
}
|
||||
this.previewUrl = '';
|
||||
this.isPreviewPdf = false;
|
||||
this.uploadDialogVisible = true;
|
||||
},
|
||||
closeUploadDialog() {
|
||||
this.uploadDialogVisible = false;
|
||||
this.uploadForm.file = null;
|
||||
this.previewUrl = '';
|
||||
},
|
||||
handleFileChange(file) {
|
||||
const isLt2M = file.size / 1024 / 1024 < 2;
|
||||
const isAcceptedType = ['image/jpeg', 'image/png', 'application/pdf'].includes(file.raw.type);
|
||||
|
||||
if (!isAcceptedType) {
|
||||
this.$message.error('上传文件只能是 JPG/PNG/PDF 格式!');
|
||||
return;
|
||||
}
|
||||
if (!isLt2M) {
|
||||
this.$message.error('上传文件大小不能超过 2MB!');
|
||||
return;
|
||||
}
|
||||
|
||||
this.uploadForm.file = file.raw;
|
||||
this.isPreviewPdf = file.raw.type === 'application/pdf';
|
||||
|
||||
this.previewUrl = URL.createObjectURL(file.raw);
|
||||
},
|
||||
handleFileRemove() {
|
||||
this.uploadForm.file = null;
|
||||
this.previewUrl = '';
|
||||
},
|
||||
submitNewUpload() {
|
||||
this.$refs.uploadForm.validate(valid => {
|
||||
if (valid) {
|
||||
if (!this.uploadForm.file) {
|
||||
this.$message.warning("请选择要上传的文件");
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("file", this.uploadForm.file);
|
||||
formData.append("id", this.receiptData.id);
|
||||
formData.append("remark", this.uploadForm.remark);
|
||||
// formData.append("totalPriceWithTax", this.uploadForm.totalPriceWithTax);
|
||||
formData.append("ticketPriceWithTax", this.uploadForm.ticketPriceWithTax);
|
||||
// formData.append("totalPriceWithoutTax", this.uploadForm.totalPriceWithoutTax);
|
||||
formData.append("ticketPriceWithoutTax", this.uploadForm.ticketPriceWithoutTax);
|
||||
// formData.append("taxAmount", this.uploadForm.taxAmount);
|
||||
formData.append("ticketType", this.uploadForm.ticketType);
|
||||
|
||||
uploadReceiptAttachment(formData)
|
||||
.then(response => {
|
||||
this.$message.success("上传成功");
|
||||
this.closeUploadDialog();
|
||||
this.fetchAttachments();
|
||||
})
|
||||
.catch(error => {
|
||||
this.$message.error("上传失败");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.receipt-dialog-body {
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.loading-spinner {
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
padding: 20px;
|
||||
}
|
||||
.receipt-card-content {
|
||||
display: flex;
|
||||
}
|
||||
.receipt-details {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.detail-item {
|
||||
display: flex;
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.item-label {
|
||||
width: 110px;
|
||||
color: #606266;
|
||||
text-align: right;
|
||||
margin-right: 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.item-value {
|
||||
color: #303133;
|
||||
}
|
||||
.image-wrapper {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
min-height: 150px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid #DCDFE6;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.void-overlay {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%) rotate(-30deg);
|
||||
color: red;
|
||||
font-size: 48px;
|
||||
font-weight: bold;
|
||||
opacity: 0.7;
|
||||
pointer-events: none;
|
||||
}
|
||||
.download-btn {
|
||||
display: block;
|
||||
}
|
||||
.upload-btn-container {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.pdf-placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 200px;
|
||||
height: 150px;
|
||||
color: #606266;
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.pdf-placeholder:hover {
|
||||
border-color: #409EFF;
|
||||
color: #409EFF;
|
||||
}
|
||||
.pdf-placeholder .el-icon-document {
|
||||
font-size: 48px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
/* New Dialog Styles */
|
||||
.upload-preview-container {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
.preview-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.preview-image {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
.preview-pdf {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
color: #606266;
|
||||
}
|
||||
.preview-pdf .el-icon-document {
|
||||
font-size: 64px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.preview-placeholder {
|
||||
text-align: center;
|
||||
color: #909399;
|
||||
}
|
||||
.placeholder-icon {
|
||||
font-size: 64px;
|
||||
margin-bottom: 10px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
.placeholder-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
.pdf-thumbnail-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.pdf-hover-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.pdf-thumbnail-container:hover .pdf-hover-overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,345 @@
|
|||
<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="receiptBillCode">
|
||||
<el-input
|
||||
v-model="queryParams.receiptBillCode"
|
||||
placeholder="请输入收票单编号"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="制造商名称" prop="vendorCode">
|
||||
<el-input
|
||||
v-model="queryParams.vendorCode"
|
||||
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="receiptBillType">
|
||||
<el-select v-model="queryParams.receiptBillType" placeholder="请选择收票单类型" clearable>
|
||||
<el-option v-for="dict in dict.type.receipt_bill_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="审批状态" prop="approveStatus">
|
||||
<el-select v-model="queryParams.approveStatus" placeholder="请选择审批状态" clearable>
|
||||
<el-option label="待提交" value="0" />
|
||||
<el-option label="审批中" value="1" />
|
||||
<el-option label="已审批" value="2" />
|
||||
<el-option label="已驳回" value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="收票状态" prop="receiptStatus">
|
||||
<el-select v-model="queryParams.receiptStatus" placeholder="请选择收票状态" clearable>
|
||||
<el-option label="待收票" value="0" />
|
||||
<el-option label="已收票" value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="审批节点" prop="approveNode">
|
||||
<el-input
|
||||
v-model="queryParams.approveNode"
|
||||
placeholder="请输入审批节点"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="审批通过时间">
|
||||
<el-date-picker
|
||||
v-model="dateRangeApproval"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="预计收票时间">
|
||||
<el-date-picker
|
||||
v-model="dateRangeEstimated"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="实际收票时间">
|
||||
<el-date-picker
|
||||
v-model="dateRangeActual"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="receiptList">
|
||||
<el-table-column label="收票单编号" align="center" prop="ticketBillCode" />
|
||||
<el-table-column label="预计收票时间" align="center" prop="ticketTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.ticketTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="制造商开票时间" align="center" prop="vendorTicketTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.vendorTicketTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="制造商名称" align="center" prop="vendorName" />
|
||||
<el-table-column label="含税总价" align="center" prop="totalPriceWithTax" />
|
||||
<el-table-column label="未税总价" align="center" prop="totalPriceWithoutTax" />
|
||||
<el-table-column label="税额" align="center" prop="taxAmount" />
|
||||
<!-- <el-table-column label="收票单类型" align="center" prop="ticketBillType" >-->
|
||||
<!-- <template slot-scope="scope">-->
|
||||
<!-- <dict-tag :options="dict.type.ticket_bill_type" :value="scope.row.ticketBillType"/>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column label="收票状态" align="center" prop="ticketStatus" >
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.receipt_status" :value="scope.row.ticketStatus"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="实际收票时间" align="center" prop="actualTicketTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.actualTicketTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="审批状态" align="center" prop="approveStatus" >
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.approve_status" :value="scope.row.approveStatus"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批通过时间" align="center" prop="approveTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.approveTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-view"
|
||||
@click="handleDetail(scope.row)"
|
||||
>查看详情</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-document"
|
||||
@click="handleReceipt(scope.row)"
|
||||
>收票附件</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-document"
|
||||
@click="handleReturn(scope.row)"
|
||||
>退回</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-refresh-left"
|
||||
v-show="scope.row.approveStatus=='2'"
|
||||
@click="handleRedRush(scope.row)"
|
||||
>申请红冲</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 详情抽屉 -->
|
||||
<detail-drawer :visible.sync="detailOpen" :detail="detailData"></detail-drawer>
|
||||
<!-- 新增弹窗 -->
|
||||
<add-form :visible.sync="addOpen" :dicts="dict.type" @submit="handleAddSubmit"></add-form>
|
||||
<!-- 收票附件弹窗 -->
|
||||
<receipt-dialog :visible.sync="receiptOpen" :receipt-data="currentRow" :dicts="dict.type"></receipt-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {listReceipt, getReceipt, redRush, addReceipt, returnReceipt} from "@/api/finance/receipt";
|
||||
import { addDateRange } from "@/utils/ruoyi";
|
||||
import DetailDrawer from "./components/DetailDrawer.vue";
|
||||
import AddForm from "./components/AddForm.vue";
|
||||
import ReceiptDialog from "./components/ReceiptDialog.vue";
|
||||
|
||||
export default {
|
||||
name: "Receipt",
|
||||
components: {
|
||||
DetailDrawer,
|
||||
AddForm,
|
||||
ReceiptDialog
|
||||
},
|
||||
dicts:['receipt_bill_type','approve_status','receipt_status'],
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 收票单表格数据
|
||||
receiptList: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
projectCode: null,
|
||||
projectName: null,
|
||||
receiptBillCode: null,
|
||||
vendorCode: null,
|
||||
payableBillCode: null,
|
||||
receiptBillType: null,
|
||||
approveStatus: null,
|
||||
receiptStatus: null,
|
||||
approveNode: null,
|
||||
},
|
||||
// 日期范围
|
||||
dateRangeApproval: [],
|
||||
dateRangeEstimated: [],
|
||||
dateRangeActual: [],
|
||||
// 详情抽屉
|
||||
detailOpen: false,
|
||||
detailData: null,
|
||||
// 新增弹窗
|
||||
addOpen: false,
|
||||
// 收票附件弹窗
|
||||
receiptOpen: false,
|
||||
currentRow: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
addDateRange,
|
||||
getList() {
|
||||
this.loading = true;
|
||||
let query = { ...this.queryParams };
|
||||
query = this.addDateRange(query, this.dateRangeApproval, 'ApproveTime');
|
||||
query = this.addDateRange(query, this.dateRangeEstimated, 'ReceiptTime');
|
||||
query = this.addDateRange(query, this.dateRangeActual, 'ActualReceiptTime');
|
||||
|
||||
listReceipt(query).then(response => {
|
||||
this.receiptList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRangeApproval = [];
|
||||
this.dateRangeEstimated = [];
|
||||
this.dateRangeActual = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.addOpen = true;
|
||||
},
|
||||
/** 新增提交 */
|
||||
handleAddSubmit(form) {
|
||||
addReceipt(form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.addOpen = false;
|
||||
this.getList();
|
||||
}).catch(error => {
|
||||
console.error("新增收票单失败", error);
|
||||
this.$modal.msgError("新增失败");
|
||||
});
|
||||
},
|
||||
/** 详情按钮操作 */
|
||||
handleDetail(row) {
|
||||
getReceipt(row.id).then(response => {
|
||||
this.detailData = response.data;
|
||||
this.detailOpen = true;
|
||||
});
|
||||
},
|
||||
/** 收票附件按钮操作 */
|
||||
handleReceipt(row) {
|
||||
this.currentRow = row;
|
||||
this.receiptOpen = true;
|
||||
},
|
||||
/** 退回按钮操作 */
|
||||
handleRedRush(row) {
|
||||
this.$modal.confirm('是否确认收票单编号为"' + row.ticketBillCode + '"的数据项进行红冲,并提交财务审批?').then(function() {
|
||||
return redRush(row.id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("退回成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleReturn(row) {
|
||||
this.$modal.confirm('是否确认退回收票单编号为"' + row.ticketBillCode + '"的数据项?').then(function() {
|
||||
return returnReceipt(row.id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("退回成功");
|
||||
}).catch(() => {});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
package com.ruoyi.sip.controller;
|
||||
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
|
||||
import com.ruoyi.sip.service.IOmsPayableTicketDetailService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 应付单收票明细Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/sip/ticketDetail")
|
||||
public class OmsPayableTicketDetailController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IOmsPayableTicketDetailService omsPayableTicketDetailService;
|
||||
|
||||
/**
|
||||
* 查询应付单收票明细列表
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketDetail:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(OmsPayableTicketDetail omsPayableTicketDetail)
|
||||
{
|
||||
startPage();
|
||||
List<OmsPayableTicketDetail> list = omsPayableTicketDetailService.selectOmsPayableTicketDetailList(omsPayableTicketDetail);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出应付单收票明细列表
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketDetail:export")
|
||||
@Log(title = "应付单收票明细", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, OmsPayableTicketDetail omsPayableTicketDetail)
|
||||
{
|
||||
List<OmsPayableTicketDetail> list = omsPayableTicketDetailService.selectOmsPayableTicketDetailList(omsPayableTicketDetail);
|
||||
ExcelUtil<OmsPayableTicketDetail> util = new ExcelUtil<OmsPayableTicketDetail>(OmsPayableTicketDetail.class);
|
||||
util.exportExcel(response, list, "应付单收票明细数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应付单收票明细详细信息
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketDetail:query")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return AjaxResult.success(omsPayableTicketDetailService.selectOmsPayableTicketDetailById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增应付单收票明细
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketDetail:add")
|
||||
@Log(title = "应付单收票明细", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody OmsPayableTicketDetail omsPayableTicketDetail)
|
||||
{
|
||||
return toAjax(omsPayableTicketDetailService.insertOmsPayableTicketDetail(omsPayableTicketDetail));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改应付单收票明细
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketDetail:edit")
|
||||
@Log(title = "应付单收票明细", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody OmsPayableTicketDetail omsPayableTicketDetail)
|
||||
{
|
||||
return toAjax(omsPayableTicketDetailService.updateOmsPayableTicketDetail(omsPayableTicketDetail));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除应付单收票明细
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketDetail:remove")
|
||||
@Log(title = "应付单收票明细", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(omsPayableTicketDetailService.deleteOmsPayableTicketDetailByIds(ids));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
package com.ruoyi.sip.controller;
|
||||
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.sip.domain.OmsPayablePaymentPlan;
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketPlan;
|
||||
import com.ruoyi.sip.service.IOmsPayableTicketPlanService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 应付单收票计划Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/finance/ticket/plan")
|
||||
public class OmsPayableTicketPlanController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IOmsPayableTicketPlanService omsPayableTicketPlanService;
|
||||
|
||||
/**
|
||||
* 查询应付单收票计划列表
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketPlan:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(OmsPayableTicketPlan omsPayableTicketPlan)
|
||||
{
|
||||
startPage();
|
||||
List<OmsPayableTicketPlan> list = omsPayableTicketPlanService.selectOmsPayableTicketPlanList(omsPayableTicketPlan);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出应付单收票计划列表
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketPlan:export")
|
||||
@Log(title = "应付单收票计划", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, OmsPayableTicketPlan omsPayableTicketPlan)
|
||||
{
|
||||
List<OmsPayableTicketPlan> list = omsPayableTicketPlanService.selectOmsPayableTicketPlanList(omsPayableTicketPlan);
|
||||
ExcelUtil<OmsPayableTicketPlan> util = new ExcelUtil<OmsPayableTicketPlan>(OmsPayableTicketPlan.class);
|
||||
util.exportExcel(response, list, "应付单收票计划数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应付单收票计划详细信息
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketPlan:query")
|
||||
@GetMapping(value = "/{payableBillId}")
|
||||
public AjaxResult getInfo(@PathVariable("payableBillId") Long payableBillId)
|
||||
{
|
||||
return AjaxResult.success(omsPayableTicketPlanService.listByPayableBillId(payableBillId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增应付单收票计划
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketPlan:add")
|
||||
@Log(title = "应付单收票计划", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody OmsPayableTicketPlan omsPayableTicketPlan)
|
||||
{
|
||||
return toAjax(omsPayableTicketPlanService.insertOmsPayableTicketPlan(omsPayableTicketPlan));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改应付单收票计划
|
||||
*/
|
||||
@PostMapping("/{payableBillId}")
|
||||
public AjaxResult updateTicketPlan(@PathVariable("payableBillId") Long payableBillId, @RequestBody List<OmsPayableTicketPlan> ticketPlanList) {
|
||||
omsPayableTicketPlanService.updateTicketPlan(payableBillId, ticketPlanList);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除应付单收票计划
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketPlan:remove")
|
||||
@Log(title = "应付单收票计划", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(omsPayableTicketPlanService.deleteOmsPayableTicketPlanByIds(ids));
|
||||
}
|
||||
}
|
||||
|
|
@ -211,20 +211,7 @@ public class OmsPaymentBillController extends BaseController
|
|||
return AjaxResult.error("操作失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
//
|
||||
// /**
|
||||
// * 上传退款图
|
||||
// */
|
||||
// @PostMapping("/uploadRefundProof")
|
||||
// @ResponseBody
|
||||
// public AjaxResult uploadRefundProof(@RequestParam("paymentBillId") Long paymentBillId, @RequestParam("file") MultipartFile file) {
|
||||
// try {
|
||||
// return omsPaymentBillService.uploadRefundProof(paymentBillId, file);
|
||||
// } catch (Exception e) {
|
||||
// logger.error("上传退款图失败", e);
|
||||
// return AjaxResult.error("操作失败:" + e.getMessage());
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,170 @@
|
|||
package com.ruoyi.sip.controller;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.ruoyi.sip.domain.OmsFinAttachment;
|
||||
import com.ruoyi.sip.service.IOmsFinAttachmentService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
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.OmsTicketBill;
|
||||
import com.ruoyi.sip.service.IOmsTicketBillService;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 采购收票单Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/finance/ticket")
|
||||
public class OmsTicketBillController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IOmsTicketBillService omsTicketBillService;
|
||||
@Autowired
|
||||
private IOmsFinAttachmentService omsFinAttachmentService;
|
||||
/**
|
||||
* 查询采购收票单列表
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketBill:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(OmsTicketBill omsTicketBill)
|
||||
{
|
||||
startPage();
|
||||
List<OmsTicketBill> list = omsTicketBillService.selectOmsTicketBillList(omsTicketBill);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出采购收票单列表
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketBill:export")
|
||||
@Log(title = "采购收票单", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, OmsTicketBill omsTicketBill)
|
||||
{
|
||||
List<OmsTicketBill> list = omsTicketBillService.selectOmsTicketBillList(omsTicketBill);
|
||||
ExcelUtil<OmsTicketBill> util = new ExcelUtil<OmsTicketBill>(OmsTicketBill.class);
|
||||
util.exportExcel(response, list, "采购收票单数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取采购收票单详细信息
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketBill:query")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return AjaxResult.success(omsTicketBillService.selectOmsTicketBillById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增采购收票单
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketBill:add")
|
||||
@Log(title = "采购收票单", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody OmsTicketBill omsTicketBill)
|
||||
{
|
||||
return toAjax(omsTicketBillService.insertOmsTicketBill(omsTicketBill));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改采购收票单
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketBill:edit")
|
||||
@Log(title = "采购收票单", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody OmsTicketBill omsTicketBill)
|
||||
{
|
||||
return toAjax(omsTicketBillService.updateOmsTicketBill(omsTicketBill));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除采购收票单
|
||||
*/
|
||||
@RequiresPermissions("sip:ticketBill:remove")
|
||||
@Log(title = "采购收票单", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(omsTicketBillService.deleteOmsTicketBillByIds(ids));
|
||||
}
|
||||
/**
|
||||
* 查看回执单页面
|
||||
*/
|
||||
@GetMapping("/attachment/{id}")
|
||||
@ResponseBody
|
||||
public AjaxResult viewReceipt(@PathVariable("id") Long id, @RequestParam("type") String type)
|
||||
{
|
||||
|
||||
return AjaxResult.success( omsFinAttachmentService.list(Collections.singletonList(id),type));
|
||||
}
|
||||
//
|
||||
/**
|
||||
* 上传回执单
|
||||
*/
|
||||
|
||||
@Log(title = "上传回执单", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/uploadReceipt")
|
||||
@ResponseBody
|
||||
public AjaxResult uploadReceipt(OmsTicketBill ticketBill, @RequestParam("file") MultipartFile file)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
return omsTicketBillService.uploadReceipt(ticketBill, file);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.error("上传回执单失败", e);
|
||||
return AjaxResult.error("操作失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请红冲
|
||||
*/
|
||||
@GetMapping("/applyRefund/{id}")
|
||||
@ResponseBody
|
||||
public AjaxResult applyRefund(@PathVariable("id") Long id) {
|
||||
try {
|
||||
return omsTicketBillService.applyRefund(id);
|
||||
} catch (Exception e) {
|
||||
logger.error("申请退款失败", e);
|
||||
return AjaxResult.error("操作失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 退回付款单
|
||||
*/
|
||||
@RequiresPermissions("finance:payment:return")
|
||||
@Log(title = "退回付款单", businessType = BusinessType.UPDATE)
|
||||
@DeleteMapping("/return/{id}")
|
||||
@ResponseBody
|
||||
public AjaxResult returnTicket(@PathVariable("id") Long id)
|
||||
{
|
||||
try {
|
||||
// 验证付款单ID
|
||||
if (id == null) {
|
||||
return AjaxResult.error("收票ID不能为空");
|
||||
}
|
||||
|
||||
// 调用服务层方法处理退回逻辑
|
||||
return omsTicketBillService.returnTicket(id);
|
||||
} catch (Exception e) {
|
||||
logger.error("退回付款单失败", e);
|
||||
return AjaxResult.error("操作失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ public class OmsFinAttachment extends BaseEntity
|
|||
|
||||
/** 付款单 */
|
||||
PAYMENT("payment", "付款单"),
|
||||
INVOICE("invoice", "收票单"),
|
||||
INVOICE("ticket", "收票单"),
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
package com.ruoyi.sip.domain;
|
||||
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 应付单收票明细对象 oms_payable_ticket_detail
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Data
|
||||
public class OmsPayableTicketDetail extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long id;
|
||||
private Long ticketPlanId;
|
||||
private Long payableBillId;
|
||||
private List<Long> payableBillIdList;
|
||||
private String payableDetailType;
|
||||
// 收票时间
|
||||
private Date paymentTime;
|
||||
// 收票金额
|
||||
private BigDecimal paymentAmount;
|
||||
// 收票比例
|
||||
private BigDecimal paymentRate;
|
||||
// 收票单号
|
||||
private String ticketBillCode;
|
||||
private Long ticketBillId;
|
||||
// 实际收票时间
|
||||
private Date actualTicketTime;
|
||||
// 收票状态
|
||||
private String ticketStatus;
|
||||
|
||||
@Getter
|
||||
public enum PayableDetailTypeEnum {
|
||||
|
||||
TICKET("1", "收票"),
|
||||
RED_RUSH("2", "红冲"),
|
||||
|
||||
|
||||
|
||||
;
|
||||
private final String code;
|
||||
private final String desc;
|
||||
|
||||
PayableDetailTypeEnum(String code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package com.ruoyi.sip.domain;
|
||||
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 应付单收票计划对象 oms_payable_ticket_plan
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Data
|
||||
public class OmsPayableTicketPlan extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键 */
|
||||
private Long id;
|
||||
|
||||
/** 应付单ID */
|
||||
private Long payableBillId;
|
||||
|
||||
/** 计划收票时间 */
|
||||
private Date planTicketDate;
|
||||
|
||||
/** 计划收票金额 */
|
||||
private BigDecimal planAmount;
|
||||
|
||||
/** 计划收票比例 */
|
||||
private BigDecimal planRate;
|
||||
|
||||
private Long detailId;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
package com.ruoyi.sip.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 采购收票单对象 oms_ticket_bill
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Data
|
||||
public class OmsTicketBill extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键ID */
|
||||
private Long id;
|
||||
|
||||
/** 收票单编号 */
|
||||
@Excel(name = "收票单编号")
|
||||
private String ticketBillCode;
|
||||
|
||||
/** 票据类型 */
|
||||
@Excel(name = "票据类型")
|
||||
private String ticketType;
|
||||
|
||||
/** 收票单类型 (FROM_PAYABLE, PRE_PAYMENT) */
|
||||
@Excel(name = "收票单类型 (FROM_PAYABLE, PRE_PAYMENT)")
|
||||
private String ticketBillType;
|
||||
|
||||
/** 制造商开票时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Excel(name = "制造商开票时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date vendorTicketTime;
|
||||
|
||||
/** 预计收票时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Excel(name = "预计收票时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date ticketTime;
|
||||
|
||||
/** 制造商编码 */
|
||||
@Excel(name = "制造商编码")
|
||||
private String vendorCode;
|
||||
private String vendorName;
|
||||
|
||||
/** 含税总价 */
|
||||
@Excel(name = "含税总价")
|
||||
private BigDecimal totalPriceWithTax;
|
||||
private BigDecimal ticketPriceWithTax;
|
||||
|
||||
/** 未税总价 */
|
||||
@Excel(name = "未税总价")
|
||||
private BigDecimal totalPriceWithoutTax;
|
||||
private BigDecimal ticketPriceWithoutTax;
|
||||
|
||||
/** 税额 */
|
||||
@Excel(name = "税额")
|
||||
@Getter(value= AccessLevel.NONE)
|
||||
private BigDecimal taxAmount;
|
||||
@Getter(value= AccessLevel.NONE)
|
||||
private BigDecimal ticketAmount;
|
||||
private BigDecimal taxRate;
|
||||
|
||||
/** 删除标志(0代表存在 2代表删除) */
|
||||
private String delFlag;
|
||||
|
||||
/** 实际收票时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Excel(name = "实际收票时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date actualTicketTime;
|
||||
|
||||
/** 收票状态 */
|
||||
@Excel(name = "收票状态")
|
||||
private String ticketStatus;
|
||||
|
||||
/** 审批状态 */
|
||||
@Excel(name = "审批状态")
|
||||
private String approveStatus;
|
||||
|
||||
/** 审批节点 */
|
||||
@Excel(name = "审批节点")
|
||||
private String approveNode;
|
||||
|
||||
/** 审批时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Excel(name = "审批时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date approveTime;
|
||||
|
||||
/** 退款状态 */
|
||||
private String refundStatus;
|
||||
|
||||
/** 应付单编号(关联查询字段) */
|
||||
@Excel(name = "应付单编号")
|
||||
private String payableBillCode;
|
||||
|
||||
/** 关联的原始收票单ID */
|
||||
private Long originalBillId;
|
||||
private List<PaymentBillPayableDetailDTO> detailList;
|
||||
|
||||
|
||||
public BigDecimal getTaxAmount() {
|
||||
if (null != totalPriceWithTax && null != totalPriceWithoutTax){
|
||||
return totalPriceWithTax.subtract(totalPriceWithoutTax);
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
public BigDecimal getTicketAmount() {
|
||||
if (null != ticketPriceWithTax && null != ticketPriceWithoutTax){
|
||||
return ticketPriceWithTax.subtract(ticketPriceWithoutTax);
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public enum TicketBillTypeEnum {
|
||||
|
||||
/** 应付单生成 */
|
||||
FROM_PAYABLE("FROM_PAYABLE", "应付单生成"),
|
||||
/** 预付单 */
|
||||
// PRE_PAYMENT("PRE_PAYMENT", "预付单"),
|
||||
/** 退款单 */
|
||||
RED_RUSH("RED_RUSH", "红冲单"),
|
||||
|
||||
|
||||
|
||||
;
|
||||
private final String code;
|
||||
private final String desc;
|
||||
TicketBillTypeEnum(String code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
@Getter
|
||||
public enum TicketStatusEnum {
|
||||
|
||||
/** 应付单生成 */
|
||||
RED_RUSH("-1", "已红冲"),
|
||||
WAIT_TICKET("1", "未收票"),
|
||||
/** 预付单 */
|
||||
TICKET("2", "已收票"),
|
||||
|
||||
|
||||
|
||||
;
|
||||
private final String code;
|
||||
private final String desc;
|
||||
TicketStatusEnum(String code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
@Getter
|
||||
public enum RefundStatusEnum {
|
||||
|
||||
/** 应付单生成 */
|
||||
REFUNDED("RED_RUSH_APPLIED", "已申请红冲"),
|
||||
WAIT_REFUNDED("WAIT_RED_RUSH", "未红冲")
|
||||
|
||||
;
|
||||
private final String code;
|
||||
private final String desc;
|
||||
RefundStatusEnum(String code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 MergedReceiptDataDto {
|
||||
private String ticketBillType;
|
||||
private Date ticketTime;
|
||||
private List<PayableOrderReceiptDto> payableOrders;
|
||||
private BigDecimal totalMergeTicketAmount;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.ruoyi.sip.domain.dto;
|
||||
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketPlan;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PayableOrderReceiptDto {
|
||||
private Long id;
|
||||
private String payableBillCode;
|
||||
private List<OmsPayableTicketPlan> ticketPlans;
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
package com.ruoyi.sip.domain.dto;
|
||||
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 收票单详情数据传输对象
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
public class TicketBillDetailDTO {
|
||||
|
||||
private String ticketBillCode;
|
||||
private String ticketType;
|
||||
private String ticketBillType;
|
||||
private String vendorCode;
|
||||
private String vendorName;
|
||||
private BigDecimal totalPriceWithTax;
|
||||
private BigDecimal totalPriceWithoutTax;
|
||||
private BigDecimal taxAmount;
|
||||
private List<OmsPayableTicketDetail> detailList;
|
||||
|
||||
public String getTicketBillCode() {
|
||||
return ticketBillCode;
|
||||
}
|
||||
|
||||
public void setTicketBillCode(String ticketBillCode) {
|
||||
this.ticketBillCode = ticketBillCode;
|
||||
}
|
||||
|
||||
public String getTicketType() {
|
||||
return ticketType;
|
||||
}
|
||||
|
||||
public void setTicketType(String ticketType) {
|
||||
this.ticketType = ticketType;
|
||||
}
|
||||
|
||||
public String getTicketBillType() {
|
||||
return ticketBillType;
|
||||
}
|
||||
|
||||
public void setTicketBillType(String ticketBillType) {
|
||||
this.ticketBillType = ticketBillType;
|
||||
}
|
||||
|
||||
public String getVendorCode() {
|
||||
return vendorCode;
|
||||
}
|
||||
|
||||
public void setVendorCode(String vendorCode) {
|
||||
this.vendorCode = vendorCode;
|
||||
}
|
||||
|
||||
public String getVendorName() {
|
||||
return vendorName;
|
||||
}
|
||||
|
||||
public void setVendorName(String vendorName) {
|
||||
this.vendorName = vendorName;
|
||||
}
|
||||
|
||||
public BigDecimal getTotalPriceWithTax() {
|
||||
return totalPriceWithTax;
|
||||
}
|
||||
|
||||
public void setTotalPriceWithTax(BigDecimal totalPriceWithTax) {
|
||||
this.totalPriceWithTax = totalPriceWithTax;
|
||||
}
|
||||
|
||||
public BigDecimal getTotalPriceWithoutTax() {
|
||||
return totalPriceWithoutTax;
|
||||
}
|
||||
|
||||
public void setTotalPriceWithoutTax(BigDecimal totalPriceWithoutTax) {
|
||||
this.totalPriceWithoutTax = totalPriceWithoutTax;
|
||||
}
|
||||
|
||||
public BigDecimal getTaxAmount() {
|
||||
return taxAmount;
|
||||
}
|
||||
|
||||
public void setTaxAmount(BigDecimal taxAmount) {
|
||||
this.taxAmount = taxAmount;
|
||||
}
|
||||
|
||||
public List<OmsPayableTicketDetail> getDetailList() {
|
||||
return detailList;
|
||||
}
|
||||
|
||||
public void setDetailList(List<OmsPayableTicketDetail> detailList) {
|
||||
this.detailList = detailList;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package com.ruoyi.sip.domain.dto;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 收票计划数据传输对象
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
public class TicketPlanDto {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long payableBillId;
|
||||
|
||||
private Date planTicketDate;
|
||||
|
||||
private BigDecimal planAmount;
|
||||
|
||||
private BigDecimal planRate;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getPayableBillId() {
|
||||
return payableBillId;
|
||||
}
|
||||
|
||||
public void setPayableBillId(Long payableBillId) {
|
||||
this.payableBillId = payableBillId;
|
||||
}
|
||||
|
||||
public Date getPlanTicketDate() {
|
||||
return planTicketDate;
|
||||
}
|
||||
|
||||
public void setPlanTicketDate(Date planTicketDate) {
|
||||
this.planTicketDate = planTicketDate;
|
||||
}
|
||||
|
||||
public BigDecimal getPlanAmount() {
|
||||
return planAmount;
|
||||
}
|
||||
|
||||
public void setPlanAmount(BigDecimal planAmount) {
|
||||
this.planAmount = planAmount;
|
||||
}
|
||||
|
||||
public BigDecimal getPlanRate() {
|
||||
return planRate;
|
||||
}
|
||||
|
||||
public void setPlanRate(BigDecimal planRate) {
|
||||
this.planRate = planRate;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package com.ruoyi.sip.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
|
||||
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
|
||||
|
||||
/**
|
||||
* 应付单收票明细Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
public interface OmsPayableTicketDetailMapper
|
||||
{
|
||||
/**
|
||||
* 查询应付单收票明细
|
||||
*
|
||||
* @param id 应付单收票明细主键
|
||||
* @return 应付单收票明细
|
||||
*/
|
||||
public OmsPayableTicketDetail selectOmsPayableTicketDetailById(Long id);
|
||||
|
||||
/**
|
||||
* 查询应付单收票明细列表
|
||||
*
|
||||
* @param omsPayableTicketDetail 应付单收票明细
|
||||
* @return 应付单收票明细集合
|
||||
*/
|
||||
public List<OmsPayableTicketDetail> selectOmsPayableTicketDetailList(OmsPayableTicketDetail omsPayableTicketDetail);
|
||||
|
||||
/**
|
||||
* 新增应付单收票明细
|
||||
*
|
||||
* @param omsPayableTicketDetail 应付单收票明细
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertOmsPayableTicketDetail(OmsPayableTicketDetail omsPayableTicketDetail);
|
||||
|
||||
/**
|
||||
* 修改应付单收票明细
|
||||
*
|
||||
* @param omsPayableTicketDetail 应付单收票明细
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateOmsPayableTicketDetail(OmsPayableTicketDetail omsPayableTicketDetail);
|
||||
|
||||
/**
|
||||
* 删除应付单收票明细
|
||||
*
|
||||
* @param id 应付单收票明细主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsPayableTicketDetailById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除应付单收票明细
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsPayableTicketDetailByIds(Long[] ids);
|
||||
|
||||
List<PaymentBillPayableDetailDTO> listByTickerCode(List<String> codeList);
|
||||
|
||||
void insertBatch(List<OmsPayableTicketDetail> addList);
|
||||
|
||||
void clearRelationPayable(String ticketBillCode);
|
||||
|
||||
List<OmsPayableTicketDetail> listByPayableBillIdList(List<Long> payableBillId);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package com.ruoyi.sip.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketPlan;
|
||||
|
||||
/**
|
||||
* 应付单收票计划Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
public interface OmsPayableTicketPlanMapper
|
||||
{
|
||||
/**
|
||||
* 查询应付单收票计划
|
||||
*
|
||||
* @param id 应付单收票计划主键
|
||||
* @return 应付单收票计划
|
||||
*/
|
||||
public OmsPayableTicketPlan selectOmsPayableTicketPlanById(Long id);
|
||||
|
||||
/**
|
||||
* 查询应付单收票计划列表
|
||||
*
|
||||
* @param omsPayableTicketPlan 应付单收票计划
|
||||
* @return 应付单收票计划集合
|
||||
*/
|
||||
public List<OmsPayableTicketPlan> selectOmsPayableTicketPlanList(OmsPayableTicketPlan omsPayableTicketPlan);
|
||||
|
||||
/**
|
||||
* 新增应付单收票计划
|
||||
*
|
||||
* @param omsPayableTicketPlan 应付单收票计划
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertOmsPayableTicketPlan(OmsPayableTicketPlan omsPayableTicketPlan);
|
||||
|
||||
/**
|
||||
* 修改应付单收票计划
|
||||
*
|
||||
* @param omsPayableTicketPlan 应付单收票计划
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateOmsPayableTicketPlan(OmsPayableTicketPlan omsPayableTicketPlan);
|
||||
|
||||
/**
|
||||
* 删除应付单收票计划
|
||||
*
|
||||
* @param id 应付单收票计划主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsPayableTicketPlanById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除应付单收票计划
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsPayableTicketPlanByIds(Long[] ids);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package com.ruoyi.sip.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.ruoyi.sip.domain.OmsTicketBill;
|
||||
|
||||
/**
|
||||
* 采购收票单Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
public interface OmsTicketBillMapper
|
||||
{
|
||||
/**
|
||||
* 查询采购收票单
|
||||
*
|
||||
* @param id 采购收票单主键
|
||||
* @return 采购收票单
|
||||
*/
|
||||
public OmsTicketBill selectOmsTicketBillById(Long id);
|
||||
|
||||
/**
|
||||
* 查询采购收票单列表
|
||||
*
|
||||
* @param omsTicketBill 采购收票单
|
||||
* @return 采购收票单集合
|
||||
*/
|
||||
public List<OmsTicketBill> selectOmsTicketBillList(OmsTicketBill omsTicketBill);
|
||||
|
||||
/**
|
||||
* 新增采购收票单
|
||||
*
|
||||
* @param omsTicketBill 采购收票单
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertOmsTicketBill(OmsTicketBill omsTicketBill);
|
||||
|
||||
/**
|
||||
* 修改采购收票单
|
||||
*
|
||||
* @param omsTicketBill 采购收票单
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateOmsTicketBill(OmsTicketBill omsTicketBill);
|
||||
|
||||
/**
|
||||
* 删除采购收票单
|
||||
*
|
||||
* @param id 采购收票单主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsTicketBillById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除采购收票单
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsTicketBillByIds(Long[] ids);
|
||||
|
||||
public int selectMaxCodeByPrefix(String codePrefix);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package com.ruoyi.sip.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
|
||||
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
|
||||
|
||||
/**
|
||||
* 应付单收票明细Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
public interface IOmsPayableTicketDetailService
|
||||
{
|
||||
/**
|
||||
* 查询应付单收票明细
|
||||
*
|
||||
* @param id 应付单收票明细主键
|
||||
* @return 应付单收票明细
|
||||
*/
|
||||
public OmsPayableTicketDetail selectOmsPayableTicketDetailById(Long id);
|
||||
|
||||
/**
|
||||
* 查询应付单收票明细列表
|
||||
*
|
||||
* @param omsPayableTicketDetail 应付单收票明细
|
||||
* @return 应付单收票明细集合
|
||||
*/
|
||||
public List<OmsPayableTicketDetail> selectOmsPayableTicketDetailList(OmsPayableTicketDetail omsPayableTicketDetail);
|
||||
|
||||
/**
|
||||
* 新增应付单收票明细
|
||||
*
|
||||
* @param omsPayableTicketDetail 应付单收票明细
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertOmsPayableTicketDetail(OmsPayableTicketDetail omsPayableTicketDetail);
|
||||
|
||||
/**
|
||||
* 修改应付单收票明细
|
||||
*
|
||||
* @param omsPayableTicketDetail 应付单收票明细
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateOmsPayableTicketDetail(OmsPayableTicketDetail omsPayableTicketDetail);
|
||||
|
||||
/**
|
||||
* 批量删除应付单收票明细
|
||||
*
|
||||
* @param ids 需要删除的主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsPayableTicketDetailByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除应付单收票明细信息
|
||||
*
|
||||
* @param id 应付单收票明细主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsPayableTicketDetailById(Long id);
|
||||
List<PaymentBillPayableDetailDTO> listByTickerCode(List<String> code);
|
||||
|
||||
void applyRefund(String originalId, String newCode);
|
||||
|
||||
void clearRelationPayable(String ticketBillCode);
|
||||
|
||||
List<OmsPayableTicketDetail> listByPayableBillIdList(List<Long> collect);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package com.ruoyi.sip.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketPlan;
|
||||
|
||||
/**
|
||||
* 应付单收票计划Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
public interface IOmsPayableTicketPlanService
|
||||
{
|
||||
/**
|
||||
* 查询应付单收票计划
|
||||
*
|
||||
* @param id 应付单收票计划主键
|
||||
* @return 应付单收票计划
|
||||
*/
|
||||
public List<OmsPayableTicketPlan> listByPayableBillId(Long id);
|
||||
|
||||
/**
|
||||
* 查询应付单收票计划列表
|
||||
*
|
||||
* @param omsPayableTicketPlan 应付单收票计划
|
||||
* @return 应付单收票计划集合
|
||||
*/
|
||||
public List<OmsPayableTicketPlan> selectOmsPayableTicketPlanList(OmsPayableTicketPlan omsPayableTicketPlan);
|
||||
|
||||
/**
|
||||
* 新增应付单收票计划
|
||||
*
|
||||
* @param omsPayableTicketPlan 应付单收票计划
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertOmsPayableTicketPlan(OmsPayableTicketPlan omsPayableTicketPlan);
|
||||
|
||||
/**
|
||||
* 修改应付单收票计划
|
||||
*
|
||||
* @param omsPayableTicketPlan 应付单收票计划
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateOmsPayableTicketPlan(OmsPayableTicketPlan omsPayableTicketPlan);
|
||||
|
||||
/**
|
||||
* 批量删除应付单收票计划
|
||||
*
|
||||
* @param ids 需要删除的主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsPayableTicketPlanByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除应付单收票计划信息
|
||||
*
|
||||
* @param id 应付单收票计划主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsPayableTicketPlanById(Long id);
|
||||
|
||||
void updateTicketPlan(Long payableBillId, List<OmsPayableTicketPlan> ticketPlanList);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package com.ruoyi.sip.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.sip.domain.OmsTicketBill;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 采购收票单Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
public interface IOmsTicketBillService
|
||||
{
|
||||
/**
|
||||
* 查询采购收票单
|
||||
*
|
||||
* @param id 采购收票单主键
|
||||
* @return 采购收票单
|
||||
*/
|
||||
public OmsTicketBill selectOmsTicketBillById(Long id);
|
||||
|
||||
/**
|
||||
* 查询采购收票单列表
|
||||
*
|
||||
* @param omsTicketBill 采购收票单
|
||||
* @return 采购收票单集合
|
||||
*/
|
||||
public List<OmsTicketBill> selectOmsTicketBillList(OmsTicketBill omsTicketBill);
|
||||
|
||||
/**
|
||||
* 新增采购收票单
|
||||
*
|
||||
* @param omsTicketBill 采购收票单
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertOmsTicketBill(OmsTicketBill omsTicketBill);
|
||||
|
||||
/**
|
||||
* 修改采购收票单
|
||||
*
|
||||
* @param omsTicketBill 采购收票单
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateOmsTicketBill(OmsTicketBill omsTicketBill);
|
||||
|
||||
/**
|
||||
* 批量删除采购收票单
|
||||
*
|
||||
* @param ids 需要删除的主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsTicketBillByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 删除采购收票单信息
|
||||
*
|
||||
* @param id 采购收票单主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOmsTicketBillById(Long id);
|
||||
|
||||
AjaxResult uploadReceipt(OmsTicketBill attachment, MultipartFile file) throws Exception;
|
||||
|
||||
AjaxResult applyRefund(Long id);
|
||||
|
||||
AjaxResult returnTicket(Long id);
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
package com.ruoyi.sip.service.impl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.ShiroUtils;
|
||||
import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
|
||||
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.sip.mapper.OmsPayableTicketDetailMapper;
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
|
||||
import com.ruoyi.sip.service.IOmsPayableTicketDetailService;
|
||||
|
||||
/**
|
||||
* 应付单收票明细Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Service
|
||||
public class OmsPayableTicketDetailServiceImpl implements IOmsPayableTicketDetailService
|
||||
{
|
||||
@Autowired
|
||||
private OmsPayableTicketDetailMapper omsPayableTicketDetailMapper;
|
||||
|
||||
/**
|
||||
* 查询应付单收票明细
|
||||
*
|
||||
* @param id 应付单收票明细主键
|
||||
* @return 应付单收票明细
|
||||
*/
|
||||
@Override
|
||||
public OmsPayableTicketDetail selectOmsPayableTicketDetailById(Long id)
|
||||
{
|
||||
return omsPayableTicketDetailMapper.selectOmsPayableTicketDetailById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询应付单收票明细列表
|
||||
*
|
||||
* @param omsPayableTicketDetail 应付单收票明细
|
||||
* @return 应付单收票明细
|
||||
*/
|
||||
@Override
|
||||
public List<OmsPayableTicketDetail> selectOmsPayableTicketDetailList(OmsPayableTicketDetail omsPayableTicketDetail)
|
||||
{
|
||||
return omsPayableTicketDetailMapper.selectOmsPayableTicketDetailList(omsPayableTicketDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增应付单收票明细
|
||||
*
|
||||
* @param omsPayableTicketDetail 应付单收票明细
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertOmsPayableTicketDetail(OmsPayableTicketDetail omsPayableTicketDetail)
|
||||
{
|
||||
omsPayableTicketDetail.setCreateTime(DateUtils.getNowDate());
|
||||
return omsPayableTicketDetailMapper.insertOmsPayableTicketDetail(omsPayableTicketDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改应付单收票明细
|
||||
*
|
||||
* @param omsPayableTicketDetail 应付单收票明细
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateOmsPayableTicketDetail(OmsPayableTicketDetail omsPayableTicketDetail)
|
||||
{
|
||||
omsPayableTicketDetail.setUpdateTime(DateUtils.getNowDate());
|
||||
return omsPayableTicketDetailMapper.updateOmsPayableTicketDetail(omsPayableTicketDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除应付单收票明细
|
||||
*
|
||||
* @param ids 需要删除的主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteOmsPayableTicketDetailByIds(Long[] ids)
|
||||
{
|
||||
return omsPayableTicketDetailMapper.deleteOmsPayableTicketDetailByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除应付单收票明细信息
|
||||
*
|
||||
* @param id 应付单收票明细主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteOmsPayableTicketDetailById(Long id)
|
||||
{
|
||||
return omsPayableTicketDetailMapper.deleteOmsPayableTicketDetailById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PaymentBillPayableDetailDTO> listByTickerCode(List<String> codeList) {
|
||||
if (CollUtil.isEmpty(codeList)){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<PaymentBillPayableDetailDTO> paymentBillPayableDetailDTOS = omsPayableTicketDetailMapper.listByTickerCode(codeList);
|
||||
for (PaymentBillPayableDetailDTO paymentBillPayableDetailDTO : paymentBillPayableDetailDTOS) {
|
||||
paymentBillPayableDetailDTO.setPaymentRate(paymentBillPayableDetailDTO.getPaymentAmount()
|
||||
.divide(paymentBillPayableDetailDTO.getTotalPriceWithTax(),4,java.math.RoundingMode.HALF_UP)
|
||||
.multiply(new BigDecimal("100")));
|
||||
}
|
||||
return paymentBillPayableDetailDTOS;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyRefund(String originalCode, String newCode) {
|
||||
OmsPayableTicketDetail query = new OmsPayableTicketDetail();
|
||||
query.setTicketBillCode(originalCode);
|
||||
List<OmsPayableTicketDetail> list = omsPayableTicketDetailMapper.selectOmsPayableTicketDetailList(query);
|
||||
if (CollUtil.isNotEmpty(list)){
|
||||
List<OmsPayableTicketDetail> addList=new ArrayList<>();
|
||||
for (OmsPayableTicketDetail detail : list) {
|
||||
OmsPayableTicketDetail temp = new OmsPayableTicketDetail();
|
||||
BeanUtil.copyProperties(detail,temp);
|
||||
temp.setId(null);
|
||||
temp.setPayableDetailType(OmsPayableTicketDetail.PayableDetailTypeEnum.RED_RUSH.getCode());
|
||||
temp.setCreateBy(ShiroUtils.getUserId().toString());
|
||||
temp.setPaymentAmount(detail.getPaymentAmount().negate());
|
||||
temp.setPaymentRate(detail.getPaymentRate().negate());
|
||||
temp.setTicketBillCode(newCode);
|
||||
temp.setRemark("退款");
|
||||
addList.add( temp);
|
||||
}
|
||||
omsPayableTicketDetailMapper.insertBatch(addList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRelationPayable(String ticketBillCode) {
|
||||
omsPayableTicketDetailMapper.clearRelationPayable(ticketBillCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OmsPayableTicketDetail> listByPayableBillIdList(List<Long> payableBillId) {
|
||||
return omsPayableTicketDetailMapper.listByPayableBillIdList(payableBillId);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
package com.ruoyi.sip.service.impl;
|
||||
|
||||
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.DateUtils;
|
||||
import com.ruoyi.common.utils.ShiroUtils;
|
||||
import com.ruoyi.sip.domain.OmsPayablePaymentDetail;
|
||||
import com.ruoyi.sip.domain.OmsPayablePaymentPlan;
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
|
||||
import com.ruoyi.sip.service.IOmsPayableTicketDetailService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.sip.mapper.OmsPayableTicketPlanMapper;
|
||||
import com.ruoyi.sip.domain.OmsPayableTicketPlan;
|
||||
import com.ruoyi.sip.service.IOmsPayableTicketPlanService;
|
||||
|
||||
/**
|
||||
* 应付单收票计划Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Service
|
||||
public class OmsPayableTicketPlanServiceImpl implements IOmsPayableTicketPlanService {
|
||||
@Autowired
|
||||
private OmsPayableTicketPlanMapper omsPayableTicketPlanMapper;
|
||||
@Autowired
|
||||
private IOmsPayableTicketDetailService detailService;
|
||||
|
||||
/**
|
||||
* 查询应付单收票计划
|
||||
*
|
||||
* @param id 应付单收票计划主键
|
||||
* @return 应付单收票计划
|
||||
*/
|
||||
@Override
|
||||
public List<OmsPayableTicketPlan> listByPayableBillId(Long payableBillId) {
|
||||
OmsPayableTicketPlan omsPayableTicketPlan = new OmsPayableTicketPlan();
|
||||
omsPayableTicketPlan.setPayableBillId(payableBillId);
|
||||
List<OmsPayableTicketPlan> omsPayableTicketPlans = omsPayableTicketPlanMapper.selectOmsPayableTicketPlanList(omsPayableTicketPlan);
|
||||
if (CollUtil.isNotEmpty(omsPayableTicketPlans)) {
|
||||
List<OmsPayableTicketDetail> omsPayablePaymentDetails = detailService.listByPayableBillIdList(omsPayableTicketPlans.stream().map(OmsPayableTicketPlan::getPayableBillId).collect(Collectors.toList()));
|
||||
Map<Long, OmsPayableTicketDetail> detailMap = omsPayablePaymentDetails.stream().collect(Collectors.toMap(OmsPayableTicketDetail::getTicketPlanId, Function.identity(),
|
||||
(v1, v2) -> v1.getCreateTime().after(v2.getCreateTime()) ? v1 : v2));
|
||||
for (OmsPayableTicketPlan plan : omsPayableTicketPlans) {
|
||||
//找到最新的一条数据 如果不是退款 那么不允许再次勾选
|
||||
OmsPayableTicketDetail detail = detailMap.get(plan.getId());
|
||||
if (detail != null && !OmsPayableTicketDetail.PayableDetailTypeEnum.RED_RUSH.getCode().equalsIgnoreCase(detail.getPayableDetailType())) {
|
||||
|
||||
plan.setDetailId(detail.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return omsPayableTicketPlans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询应付单收票计划列表
|
||||
*
|
||||
* @param omsPayableTicketPlan 应付单收票计划
|
||||
* @return 应付单收票计划
|
||||
*/
|
||||
@Override
|
||||
public List<OmsPayableTicketPlan> selectOmsPayableTicketPlanList(OmsPayableTicketPlan omsPayableTicketPlan) {
|
||||
return omsPayableTicketPlanMapper.selectOmsPayableTicketPlanList(omsPayableTicketPlan);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增应付单收票计划
|
||||
*
|
||||
* @param omsPayableTicketPlan 应付单收票计划
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertOmsPayableTicketPlan(OmsPayableTicketPlan omsPayableTicketPlan) {
|
||||
omsPayableTicketPlan.setCreateTime(DateUtils.getNowDate());
|
||||
return omsPayableTicketPlanMapper.insertOmsPayableTicketPlan(omsPayableTicketPlan);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改应付单收票计划
|
||||
*
|
||||
* @param omsPayableTicketPlan 应付单收票计划
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateOmsPayableTicketPlan(OmsPayableTicketPlan omsPayableTicketPlan) {
|
||||
omsPayableTicketPlan.setUpdateTime(DateUtils.getNowDate());
|
||||
return omsPayableTicketPlanMapper.updateOmsPayableTicketPlan(omsPayableTicketPlan);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除应付单收票计划
|
||||
*
|
||||
* @param ids 需要删除的主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteOmsPayableTicketPlanByIds(Long[] ids) {
|
||||
return omsPayableTicketPlanMapper.deleteOmsPayableTicketPlanByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除应付单收票计划信息
|
||||
*
|
||||
* @param id 应付单收票计划主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteOmsPayableTicketPlanById(Long id) {
|
||||
return omsPayableTicketPlanMapper.deleteOmsPayableTicketPlanById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTicketPlan(Long payableBillId, List<OmsPayableTicketPlan> ticketPlanList) {
|
||||
// 获取数据库中现有付款计划的ID
|
||||
List<OmsPayableTicketPlan> omsPayableTicketPlans = listByPayableBillId(payableBillId);
|
||||
Set<Long> existingPlanIdSet = omsPayableTicketPlans.stream().map(OmsPayableTicketPlan::getId).collect(Collectors.toSet());
|
||||
|
||||
// 用于存放前端传入的有效(非新增或已删除)的计划ID
|
||||
Set<Long> incomingPlanIdSet = ticketPlanList.stream()
|
||||
.filter(plan -> plan.getId() != null)
|
||||
.map(OmsPayableTicketPlan::getId)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
for (OmsPayableTicketPlan plan : ticketPlanList) {
|
||||
plan.setPayableBillId(payableBillId);
|
||||
if (plan.getId() == null) {
|
||||
// 新增付款计划
|
||||
plan.setCreateBy(ShiroUtils.getLoginName());
|
||||
omsPayableTicketPlanMapper.insertOmsPayableTicketPlan(plan);
|
||||
} else if (existingPlanIdSet.contains(plan.getId())) {
|
||||
// 更新现有付款计划
|
||||
omsPayableTicketPlanMapper.updateOmsPayableTicketPlan(plan);
|
||||
}
|
||||
// 如果plan.getId()不为null但不在existingPlanIdSet中,说明是前端新添加但带有id的脏数据,或者是非法数据,这里不处理
|
||||
}
|
||||
|
||||
// 删除数据库中存在但前端未提交的付款计划
|
||||
existingPlanIdSet.removeAll(incomingPlanIdSet);
|
||||
for (Long idToDelete : existingPlanIdSet) {
|
||||
omsPayableTicketPlanMapper.deleteOmsPayableTicketPlanById(idToDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
package com.ruoyi.sip.service.impl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.enums.ApproveStatusEnum;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.ShiroUtils;
|
||||
import com.ruoyi.common.utils.file.FileUploadUtils;
|
||||
import com.ruoyi.sip.domain.OmsFinAttachment;
|
||||
import com.ruoyi.sip.domain.OmsPaymentBill;
|
||||
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
|
||||
import com.ruoyi.sip.service.IOmsFinAttachmentService;
|
||||
import com.ruoyi.sip.service.IOmsPayableTicketDetailService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.sip.mapper.OmsTicketBillMapper;
|
||||
import com.ruoyi.sip.domain.OmsTicketBill;
|
||||
import com.ruoyi.sip.service.IOmsTicketBillService;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 采购收票单Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-12-09
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
public class OmsTicketBillServiceImpl implements IOmsTicketBillService
|
||||
{
|
||||
@Autowired
|
||||
private OmsTicketBillMapper omsTicketBillMapper;
|
||||
@Autowired
|
||||
private IOmsPayableTicketDetailService payableTicketDetailService;
|
||||
@Autowired
|
||||
private IOmsFinAttachmentService omsFinAttachmentService;
|
||||
|
||||
/**
|
||||
* 查询采购收票单
|
||||
*
|
||||
* @param id 采购收票单主键
|
||||
* @return 采购收票单
|
||||
*/
|
||||
@Override
|
||||
public OmsTicketBill selectOmsTicketBillById(Long id)
|
||||
{
|
||||
OmsTicketBill omsTicketBill = omsTicketBillMapper.selectOmsTicketBillById(id);
|
||||
List<PaymentBillPayableDetailDTO> paymentBillPayableDetailDTOS = payableTicketDetailService.listByTickerCode(Collections.singletonList(omsTicketBill.getTicketBillCode()));
|
||||
omsTicketBill.setDetailList(paymentBillPayableDetailDTOS);
|
||||
return omsTicketBill;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询采购收票单列表
|
||||
*
|
||||
* @param omsTicketBill 采购收票单
|
||||
* @return 采购收票单
|
||||
*/
|
||||
@Override
|
||||
public List<OmsTicketBill> selectOmsTicketBillList(OmsTicketBill omsTicketBill)
|
||||
{
|
||||
return omsTicketBillMapper.selectOmsTicketBillList(omsTicketBill);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增采购收票单
|
||||
*
|
||||
* @param omsTicketBill 采购收票单
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertOmsTicketBill(OmsTicketBill omsTicketBill)
|
||||
{
|
||||
omsTicketBill.setTicketBillCode(generateTicketBillCode());
|
||||
omsTicketBill.setCreateTime(DateUtils.getNowDate());
|
||||
return omsTicketBillMapper.insertOmsTicketBill(omsTicketBill);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成收票单编号 CS+YYMMdd+当日序列号
|
||||
* @return 收票单编号
|
||||
*/
|
||||
private String generateTicketBillCode() {
|
||||
String prefix = "SP";
|
||||
// 查询当天已有的最大序列号
|
||||
String codePrefix = prefix + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_PATTERN);
|
||||
int maxSequence = omsTicketBillMapper.selectMaxCodeByPrefix(codePrefix);
|
||||
// 生成新的序列号
|
||||
int newSequence = maxSequence + 1;
|
||||
// 序列号补零到4位
|
||||
String sequenceStr = String.format("%04d", newSequence);
|
||||
return codePrefix + sequenceStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改采购收票单
|
||||
*
|
||||
* @param omsTicketBill 采购收票单
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateOmsTicketBill(OmsTicketBill omsTicketBill)
|
||||
{
|
||||
omsTicketBill.setUpdateTime(DateUtils.getNowDate());
|
||||
return omsTicketBillMapper.updateOmsTicketBill(omsTicketBill);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除采购收票单
|
||||
*
|
||||
* @param ids 需要删除的主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteOmsTicketBillByIds(Long[] ids)
|
||||
{
|
||||
return omsTicketBillMapper.deleteOmsTicketBillByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除采购收票单信息
|
||||
*
|
||||
* @param id 采购收票单主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteOmsTicketBillById(Long id)
|
||||
{
|
||||
return omsTicketBillMapper.deleteOmsTicketBillById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult uploadReceipt(OmsTicketBill bill, MultipartFile file) throws Exception {
|
||||
OmsFinAttachment attachment = new OmsFinAttachment();
|
||||
attachment.setRelatedBillType(OmsFinAttachment.RelatedBillTypeEnum.INVOICE.getCode());
|
||||
attachment.setRemark(bill.getRemark());
|
||||
attachment.setRelatedBillId(bill.getId());
|
||||
OmsTicketBill omsTicketBill = selectOmsTicketBillById(bill.getId());
|
||||
if (omsTicketBill == null) {
|
||||
return AjaxResult.error("收票单不存在");
|
||||
}
|
||||
if (omsTicketBill.getTotalPriceWithTax().compareTo(bill.getTicketPriceWithTax()) != 0){
|
||||
return AjaxResult.error("票据金额不一致");
|
||||
}
|
||||
|
||||
if (file.isEmpty())
|
||||
{
|
||||
return AjaxResult.error("上传文件不能为空");
|
||||
}
|
||||
// 上传文件路径
|
||||
String filePath = RuoYiConfig.getUploadPath();
|
||||
// 上传并返回新文件名称
|
||||
String fileName = FileUploadUtils.upload(filePath, file);
|
||||
|
||||
SysUser loginUser = ShiroUtils.getSysUser();
|
||||
|
||||
|
||||
attachment.setFileName(file.getOriginalFilename());
|
||||
attachment.setFilePath(fileName);
|
||||
attachment.setFileSize(file.getSize());
|
||||
attachment.setFileType(file.getContentType());
|
||||
attachment.setCreateBy(loginUser.getUserId().toString());
|
||||
omsFinAttachmentService.insertOmsFinAttachment(attachment);
|
||||
omsTicketBill.setActualTicketTime(DateUtils.getNowDate());
|
||||
omsTicketBill.setTicketStatus(OmsTicketBill.TicketStatusEnum.TICKET.getCode());
|
||||
omsTicketBill.setTicketPriceWithTax(bill.getTicketPriceWithTax());
|
||||
omsTicketBill.setTicketPriceWithoutTax(bill.getTicketPriceWithoutTax());
|
||||
omsTicketBill.setTicketType(bill.getTicketType());
|
||||
updateOmsTicketBill(omsTicketBill);
|
||||
|
||||
return AjaxResult.success(attachment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult applyRefund(Long originalId) {
|
||||
// 1. 验证原始付款单
|
||||
OmsTicketBill originalBill = selectOmsTicketBillById(originalId);
|
||||
if (originalBill == null) {
|
||||
return AjaxResult.error("原始付款单不存在");
|
||||
}
|
||||
if (!OmsTicketBill.TicketStatusEnum.TICKET.getCode().equals(originalBill.getTicketStatus())) {
|
||||
return AjaxResult.error("只有已收票的订单才能申请红冲");
|
||||
}
|
||||
if (OmsTicketBill.RefundStatusEnum.REFUNDED.getCode().equals(originalBill.getRefundStatus())) {
|
||||
return AjaxResult.error("该付款单已申请过红冲,请勿重复操作");
|
||||
}
|
||||
|
||||
// 2. 创建新的退款单
|
||||
OmsTicketBill refundBill = new OmsTicketBill();
|
||||
|
||||
// 复制属性并取反金额
|
||||
refundBill.setTotalPriceWithTax(originalBill.getTotalPriceWithTax().negate());
|
||||
refundBill.setTotalPriceWithoutTax(originalBill.getTotalPriceWithoutTax().negate());
|
||||
refundBill.setTaxAmount(originalBill.getTaxAmount().negate());
|
||||
refundBill.setTicketTime(originalBill.getTicketTime());
|
||||
refundBill.setVendorTicketTime(originalBill.getVendorTicketTime());
|
||||
refundBill.setVendorCode(originalBill.getVendorCode());
|
||||
|
||||
refundBill.setTicketBillCode(generateTicketBillCode());
|
||||
refundBill.setTicketType(originalBill.getTicketType());
|
||||
// 设置新属性
|
||||
refundBill.setTicketBillType(OmsTicketBill.TicketBillTypeEnum.RED_RUSH.getCode());
|
||||
refundBill.setRefundStatus(OmsTicketBill.RefundStatusEnum.REFUNDED.getCode());
|
||||
refundBill.setApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode());
|
||||
refundBill.setOriginalBillId(originalBill.getId());
|
||||
refundBill.setActualTicketTime(null);
|
||||
refundBill.setApproveTime(null);
|
||||
refundBill.setRemark("退款-关联原付款单:" + originalBill.getTicketBillCode());
|
||||
|
||||
insertOmsTicketBill(refundBill);
|
||||
|
||||
// 3. 更新原始付款单状态
|
||||
originalBill.setRefundStatus(OmsTicketBill.RefundStatusEnum.REFUNDED.getCode());
|
||||
|
||||
updateOmsTicketBill(originalBill);
|
||||
//4 创建付款明细
|
||||
payableTicketDetailService.applyRefund(originalBill.getTicketBillCode(),refundBill.getTicketBillCode());
|
||||
//5.todo 开始退款审批流程
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return AjaxResult.success("退款申请已提交,新的退款单号为:" + refundBill.getTicketBillCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult returnTicket(Long id) {
|
||||
try {
|
||||
// 1. 验证付款单是否存在
|
||||
OmsTicketBill ticketBill = selectOmsTicketBillById(id);
|
||||
if (ticketBill == null) {
|
||||
return AjaxResult.error("付款单不存在");
|
||||
}
|
||||
|
||||
// 2. 检查付款单类型,只有FROM_PAYABLE类型的付款单才能退回
|
||||
if (!OmsTicketBill.TicketBillTypeEnum.FROM_PAYABLE.getCode().equals(ticketBill.getTicketBillType())) {
|
||||
return AjaxResult.error("只有由应付单合并生成的收票单才能执行退回操作");
|
||||
}
|
||||
|
||||
// 3. 清楚关联
|
||||
payableTicketDetailService.clearRelationPayable(ticketBill.getTicketBillCode());
|
||||
|
||||
|
||||
// 6. 删除付款单记录
|
||||
int result = deleteOmsTicketBillById(id);
|
||||
if (result <= 0) {
|
||||
throw new RuntimeException("删除付款单失败");
|
||||
}
|
||||
|
||||
return AjaxResult.success("付款单退回成功!");
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("退回付款单操作失败:" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
<?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.OmsPayableTicketDetailMapper">
|
||||
|
||||
<resultMap type="com.ruoyi.sip.domain.OmsPayableTicketDetail" id="OmsPayableTicketDetailResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="ticketPlanId" column="ticket_plan_id" />
|
||||
<result property="payableBillId" column="payable_bill_id" />
|
||||
<result property="paymentTime" column="payment_time" />
|
||||
<result property="paymentAmount" column="payment_amount" />
|
||||
<result property="paymentRate" column="payment_rate" />
|
||||
<result property="ticketBillCode" column="ticket_bill_code" />
|
||||
<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="actualTicketTime" column="actual_ticket_time" />
|
||||
<result property="ticketStatus" column="ticket_status" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectOmsPayableTicketDetailVo">
|
||||
select id, ticket_plan_id, payable_bill_id, payment_time, payment_amount, payment_rate, ticket_bill_code,
|
||||
create_by, create_time, update_by, update_time, remark
|
||||
from oms_payable_ticket_detail
|
||||
</sql>
|
||||
|
||||
<select id="selectOmsPayableTicketDetailList" parameterType="com.ruoyi.sip.domain.OmsPayableTicketDetail" resultMap="OmsPayableTicketDetailResult">
|
||||
<include refid="selectOmsPayableTicketDetailVo"/>
|
||||
<where>
|
||||
<if test="ticketPlanId != null">
|
||||
and ticket_plan_id = #{ticketPlanId}
|
||||
</if>
|
||||
<if test="payableBillId != null">
|
||||
and payable_bill_id = #{payableBillId}
|
||||
</if>
|
||||
<if test="paymentTime != null">
|
||||
and payment_time = #{paymentTime}
|
||||
</if>
|
||||
<if test="paymentAmount != null">
|
||||
and payment_amount = #{paymentAmount}
|
||||
</if>
|
||||
<if test="paymentRate != null">
|
||||
and payment_rate = #{paymentRate}
|
||||
</if>
|
||||
<if test="ticketBillCode != null and ticketBillCode != ''">
|
||||
and ticket_bill_code = #{ticketBillCode}
|
||||
</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 like concat('%', #{remark}, '%')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectOmsPayableTicketDetailById" parameterType="Long" resultMap="OmsPayableTicketDetailResult">
|
||||
<include refid="selectOmsPayableTicketDetailVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
<select id="listByTickerCode" resultType="com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO">
|
||||
select t1.payment_amount, t2.payable_bill_code, t4.project_name, t4.project_code, t2.total_price_with_tax
|
||||
from (SELECT sum(payment_amount) payment_amount,
|
||||
payable_bill_id
|
||||
FROM oms_payable_ticket_detail
|
||||
WHERE ticket_bill_code in
|
||||
<foreach item="item" collection="list" separator="," open="(" close=")" index="">
|
||||
#{item}
|
||||
</foreach>
|
||||
group by payable_bill_id) t1
|
||||
left join oms_payable_bill t2 on t1.payable_bill_id = t2.id
|
||||
left join project_order_info t3 on t2.order_code = t3.order_code
|
||||
left join project_info t4 on t3.project_id = t4.id
|
||||
</select>
|
||||
<select id="listByPayableBillIdList" resultType="com.ruoyi.sip.domain.OmsPayableTicketDetail">
|
||||
SELECT
|
||||
t1.*,t2.actual_ticket_time,t2.ticket_status,t2.id as paymentBillId
|
||||
FROM
|
||||
oms_payable_ticket_detail t1
|
||||
LEFT JOIN oms_ticket_bill t2 ON t1.ticket_bill_code = t2.ticket_bill_code
|
||||
<where>
|
||||
|
||||
<if test="list != null and list.size>0">
|
||||
and t1.payable_bill_id in
|
||||
<foreach item="item" collection="list" separator="," open="(" close=")" index="">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<insert id="insertOmsPayableTicketDetail" parameterType="com.ruoyi.sip.domain.OmsPayableTicketDetail" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into oms_payable_ticket_detail
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="ticketPlanId != null">
|
||||
ticket_plan_id,
|
||||
</if>
|
||||
<if test="payableBillId != null">
|
||||
payable_bill_id,
|
||||
</if>
|
||||
<if test="paymentTime != null">
|
||||
payment_time,
|
||||
</if>
|
||||
<if test="paymentAmount != null">
|
||||
payment_amount,
|
||||
</if>
|
||||
<if test="paymentRate != null">
|
||||
payment_rate,
|
||||
</if>
|
||||
<if test="ticketBillCode != null and ticketBillCode != ''">
|
||||
ticket_bill_code,
|
||||
</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="ticketPlanId != null">
|
||||
#{ticketPlanId},
|
||||
</if>
|
||||
<if test="payableBillId != null">
|
||||
#{payableBillId},
|
||||
</if>
|
||||
<if test="paymentTime != null">
|
||||
#{paymentTime},
|
||||
</if>
|
||||
<if test="paymentAmount != null">
|
||||
#{paymentAmount},
|
||||
</if>
|
||||
<if test="paymentRate != null">
|
||||
#{paymentRate},
|
||||
</if>
|
||||
<if test="ticketBillCode != null and ticketBillCode != ''">
|
||||
#{ticketBillCode},
|
||||
</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>
|
||||
<insert id="insertBatch">
|
||||
insert into oms_payable_ticket_detail (payable_bill_id, ticket_plan_id, payment_time, payment_amount, payment_rate,
|
||||
ticket_bill_code, create_by, create_time, update_by, update_time, remark) values
|
||||
<foreach item="item" collection="list" separator=",">
|
||||
(#{item.payableBillId}, #{item.ticketPlanId}, #{item.paymentTime}, #{item.paymentAmount}, #{item.paymentRate}, #{item.ticketBillCode},
|
||||
#{item.createBy}, #{item.createTime}, #{item.updateBy}, #{item.updateTime}, #{item.remark})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<update id="updateOmsPayableTicketDetail" parameterType="com.ruoyi.sip.domain.OmsPayableTicketDetail">
|
||||
update oms_payable_ticket_detail
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="ticketPlanId != null">
|
||||
ticket_plan_id = #{ticketPlanId},
|
||||
</if>
|
||||
<if test="payableBillId != null">
|
||||
payable_bill_id = #{payableBillId},
|
||||
</if>
|
||||
<if test="paymentTime != null">
|
||||
payment_time = #{paymentTime},
|
||||
</if>
|
||||
<if test="paymentAmount != null">
|
||||
payment_amount = #{paymentAmount},
|
||||
</if>
|
||||
<if test="paymentRate != null">
|
||||
payment_rate = #{paymentRate},
|
||||
</if>
|
||||
<if test="ticketBillCode != null and ticketBillCode != ''">
|
||||
ticket_bill_code = #{ticketBillCode},
|
||||
</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>
|
||||
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteOmsPayableTicketDetailById" parameterType="Long">
|
||||
delete from oms_payable_ticket_detail where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteOmsPayableTicketDetailByIds" parameterType="String">
|
||||
delete from oms_payable_ticket_detail where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
<delete id="clearRelationPayable">
|
||||
delete from oms_payable_ticket_detail where ticket_bill_code = #{code}
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
<?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.OmsPayableTicketPlanMapper">
|
||||
|
||||
<resultMap type="com.ruoyi.sip.domain.OmsPayableTicketPlan" id="OmsPayableTicketPlanResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="payableBillId" column="payable_bill_id" />
|
||||
<result property="planTicketDate" column="plan_ticket_date" />
|
||||
<result property="planAmount" column="plan_amount" />
|
||||
<result property="planRate" column="plan_rate" />
|
||||
<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="selectOmsPayableTicketPlanVo">
|
||||
select id, payable_bill_id, plan_ticket_date, plan_amount, plan_rate, create_by, create_time, update_by, update_time
|
||||
from oms_payable_ticket_plan
|
||||
</sql>
|
||||
|
||||
<select id="selectOmsPayableTicketPlanList" parameterType="com.ruoyi.sip.domain.OmsPayableTicketPlan" resultMap="OmsPayableTicketPlanResult">
|
||||
<include refid="selectOmsPayableTicketPlanVo"/>
|
||||
<where>
|
||||
<if test="payableBillId != null">
|
||||
and payable_bill_id = #{payableBillId}
|
||||
</if>
|
||||
<if test="planTicketDate != null">
|
||||
and plan_ticket_date = #{planTicketDate}
|
||||
</if>
|
||||
<if test="planAmount != null">
|
||||
and plan_amount = #{planAmount}
|
||||
</if>
|
||||
<if test="planRate != null">
|
||||
and plan_rate = #{planRate}
|
||||
</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>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectOmsPayableTicketPlanById" parameterType="Long" resultMap="OmsPayableTicketPlanResult">
|
||||
<include refid="selectOmsPayableTicketPlanVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<insert id="insertOmsPayableTicketPlan" parameterType="com.ruoyi.sip.domain.OmsPayableTicketPlan" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into oms_payable_ticket_plan
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="payableBillId != null">
|
||||
payable_bill_id,
|
||||
</if>
|
||||
<if test="planTicketDate != null">
|
||||
plan_ticket_date,
|
||||
</if>
|
||||
<if test="planAmount != null">
|
||||
plan_amount,
|
||||
</if>
|
||||
<if test="planRate != null">
|
||||
plan_rate,
|
||||
</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>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="payableBillId != null">
|
||||
#{payableBillId},
|
||||
</if>
|
||||
<if test="planTicketDate != null">
|
||||
#{planTicketDate},
|
||||
</if>
|
||||
<if test="planAmount != null">
|
||||
#{planAmount},
|
||||
</if>
|
||||
<if test="planRate != null">
|
||||
#{planRate},
|
||||
</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>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateOmsPayableTicketPlan" parameterType="com.ruoyi.sip.domain.OmsPayableTicketPlan">
|
||||
update oms_payable_ticket_plan
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="payableBillId != null">
|
||||
payable_bill_id = #{payableBillId},
|
||||
</if>
|
||||
<if test="planTicketDate != null">
|
||||
plan_ticket_date = #{planTicketDate},
|
||||
</if>
|
||||
<if test="planAmount != null">
|
||||
plan_amount = #{planAmount},
|
||||
</if>
|
||||
<if test="planRate != null">
|
||||
plan_rate = #{planRate},
|
||||
</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>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteOmsPayableTicketPlanById" parameterType="Long">
|
||||
delete from oms_payable_ticket_plan where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteOmsPayableTicketPlanByIds" parameterType="String">
|
||||
delete from oms_payable_ticket_plan where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,337 @@
|
|||
<?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.OmsTicketBillMapper">
|
||||
|
||||
<resultMap type="com.ruoyi.sip.domain.OmsTicketBill" id="OmsTicketBillResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="ticketBillCode" column="ticket_bill_code" />
|
||||
<result property="ticketType" column="ticket_type" />
|
||||
<result property="ticketBillType" column="ticket_bill_type" />
|
||||
<result property="vendorTicketTime" column="vendor_ticket_time" />
|
||||
<result property="ticketTime" column="ticket_time" />
|
||||
<result property="vendorCode" column="vendor_code" />
|
||||
<result property="totalPriceWithTax" column="total_price_with_tax" />
|
||||
<result property="totalPriceWithoutTax" column="total_price_without_tax" />
|
||||
<result property="taxRate" column="tax_rate" />
|
||||
<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="actualTicketTime" column="actual_ticket_time" />
|
||||
<result property="ticketStatus" column="ticket_status" />
|
||||
<result property="approveStatus" column="approve_status" />
|
||||
<result property="approveNode" column="approve_node" />
|
||||
<result property="approveTime" column="approve_time" />
|
||||
<result property="refundStatus" column="refund_status" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectOmsTicketBillVo">
|
||||
select t1.id, t1.ticket_bill_code, t1.ticket_type, t1.ticket_bill_type, t1.vendor_ticket_time, t1.ticket_time, t1.vendor_code,
|
||||
t1.total_price_with_tax, t1.total_price_without_tax, t1.ticket_price_with_tax, t1.ticket_price_without_tax, t1.tax_rate, t1.create_by, t1.create_time, t1.update_by,
|
||||
t1.update_time, t1.remark, t1.del_flag, t1.actual_ticket_time, t1.ticket_status, t1.approve_status, t1.approve_node, t1.approve_time, t1.refund_status
|
||||
,t2.vendor_name
|
||||
from oms_ticket_bill t1
|
||||
left join oms_vendor_info t2 on t1.vendor_code=t2.vendor_code
|
||||
</sql>
|
||||
|
||||
<select id="selectOmsTicketBillList" parameterType="com.ruoyi.sip.domain.OmsTicketBill" resultMap="OmsTicketBillResult">
|
||||
<include refid="selectOmsTicketBillVo"/>
|
||||
<where>
|
||||
<if test="ticketBillCode != null and ticketBillCode != ''">
|
||||
and ticket_bill_code = #{ticketBillCode}
|
||||
</if>
|
||||
<if test="ticketType != null and ticketType != ''">
|
||||
and ticket_type = #{ticketType}
|
||||
</if>
|
||||
<if test="ticketBillType != null and ticketBillType != ''">
|
||||
and ticket_bill_type = #{ticketBillType}
|
||||
</if>
|
||||
<if test="vendorCode != null and vendorCode != ''">
|
||||
and vendor_code = #{vendorCode}
|
||||
</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="taxRate != null">
|
||||
and tax_rate = #{taxRate}
|
||||
</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 like concat('%', #{remark}, '%')
|
||||
</if>
|
||||
<if test="delFlag != null and delFlag != ''">
|
||||
and del_flag = #{delFlag}
|
||||
</if>
|
||||
<if test="actualTicketTime != null">
|
||||
and actual_ticket_time = #{actualTicketTime}
|
||||
</if>
|
||||
<if test="ticketStatus != null and ticketStatus != ''">
|
||||
and ticket_status = #{ticketStatus}
|
||||
</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="refundStatus != null and refundStatus != ''">
|
||||
and refund_status = #{refundStatus}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectOmsTicketBillById" parameterType="Long" resultMap="OmsTicketBillResult">
|
||||
<include refid="selectOmsTicketBillVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<insert id="insertOmsTicketBill" parameterType="com.ruoyi.sip.domain.OmsTicketBill" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into oms_ticket_bill
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="ticketBillCode != null and ticketBillCode != ''">
|
||||
ticket_bill_code,
|
||||
</if>
|
||||
<if test="ticketType != null and ticketType != ''">
|
||||
ticket_type,
|
||||
</if>
|
||||
<if test="ticketBillType != null and ticketBillType != ''">
|
||||
ticket_bill_type,
|
||||
</if>
|
||||
<if test="vendorTicketTime != null">
|
||||
vendor_ticket_time,
|
||||
</if>
|
||||
<if test="ticketTime != null">
|
||||
ticket_time,
|
||||
</if>
|
||||
<if test="vendorCode != null and vendorCode != ''">
|
||||
vendor_code,
|
||||
</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="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="actualTicketTime != null">
|
||||
actual_ticket_time,
|
||||
</if>
|
||||
<if test="ticketStatus != null and ticketStatus != ''">
|
||||
ticket_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="refundStatus != null and refundStatus != ''">
|
||||
refund_status,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="ticketBillCode != null and ticketBillCode != ''">
|
||||
#{ticketBillCode},
|
||||
</if>
|
||||
<if test="ticketType != null and ticketType != ''">
|
||||
#{ticketType},
|
||||
</if>
|
||||
<if test="ticketBillType != null and ticketBillType != ''">
|
||||
#{ticketBillType},
|
||||
</if>
|
||||
<if test="vendorTicketTime != null">
|
||||
#{vendorTicketTime},
|
||||
</if>
|
||||
<if test="ticketTime != null">
|
||||
#{ticketTime},
|
||||
</if>
|
||||
<if test="vendorCode != null and vendorCode != ''">
|
||||
#{vendorCode},
|
||||
</if>
|
||||
<if test="totalPriceWithTax != null">
|
||||
#{totalPriceWithTax},
|
||||
</if>
|
||||
<if test="totalPriceWithoutTax != null">
|
||||
#{totalPriceWithoutTax},
|
||||
</if>
|
||||
<if test="taxRate != null">
|
||||
#{taxRate},
|
||||
</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="actualTicketTime != null">
|
||||
#{actualTicketTime},
|
||||
</if>
|
||||
<if test="ticketStatus != null and ticketStatus != ''">
|
||||
#{ticketStatus},
|
||||
</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="refundStatus != null and refundStatus != ''">
|
||||
#{refundStatus},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateOmsTicketBill" parameterType="com.ruoyi.sip.domain.OmsTicketBill">
|
||||
update oms_ticket_bill
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="ticketBillCode != null and ticketBillCode != ''">
|
||||
ticket_bill_code = #{ticketBillCode},
|
||||
</if>
|
||||
<if test="ticketType != null and ticketType != ''">
|
||||
ticket_type = #{ticketType},
|
||||
</if>
|
||||
<if test="ticketBillType != null and ticketBillType != ''">
|
||||
ticket_bill_type = #{ticketBillType},
|
||||
</if>
|
||||
<if test="vendorTicketTime != null">
|
||||
vendor_ticket_time = #{vendorTicketTime},
|
||||
</if>
|
||||
<if test="ticketTime != null">
|
||||
ticket_time = #{ticketTime},
|
||||
</if>
|
||||
<if test="vendorCode != null and vendorCode != ''">
|
||||
vendor_code = #{vendorCode},
|
||||
</if>
|
||||
<if test="totalPriceWithTax != null">
|
||||
total_price_with_tax = #{totalPriceWithTax},
|
||||
</if>
|
||||
<if test="ticketPriceWithTax != null">
|
||||
ticket_price_with_tax = #{ticketPriceWithTax},
|
||||
</if>
|
||||
<if test="totalPriceWithoutTax != null">
|
||||
total_price_without_tax = #{totalPriceWithoutTax},
|
||||
</if>
|
||||
<if test="ticketPriceWithoutTax != null">
|
||||
ticket_price_without_tax = #{ticketPriceWithoutTax},
|
||||
</if>
|
||||
<if test="taxRate != null">
|
||||
tax_rate = #{taxRate},
|
||||
</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="actualTicketTime != null">
|
||||
actual_ticket_time = #{actualTicketTime},
|
||||
</if>
|
||||
<if test="ticketStatus != null and ticketStatus != ''">
|
||||
ticket_status = #{ticketStatus},
|
||||
</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="refundStatus != null and refundStatus != ''">
|
||||
refund_status = #{refundStatus},
|
||||
</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteOmsTicketBillById" parameterType="Long">
|
||||
delete from oms_ticket_bill where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteOmsTicketBillByIds" parameterType="String">
|
||||
delete from oms_ticket_bill where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
|
||||
<select id="selectMaxCodeByPrefix" resultType="int">
|
||||
SELECT COALESCE(MAX(CAST(SUBSTRING(ticket_bill_code, -4) AS UNSIGNED)), 0)
|
||||
FROM oms_ticket_bill
|
||||
WHERE ticket_bill_code LIKE CONCAT(#{codePrefix}, '%')
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue