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());
|
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", "付款单"),
|
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