Compare commits

..

5 Commits

Author SHA1 Message Date
chenhao 54e7d394bb feat(invoice): 新增收票单管理功能
- 新增收票单列表页面,支持查询、新增、查看详情等操作
- 实现收票单新增表单,支持选择客户、关联应收单及收票计划
- 开发收票单详情抽屉,展示收票单基本信息及关联应收单明细
- 添加收票附件上传对话框,支持上传并查看收票相关附件
- 在应收单编辑页面增加开票明细展示及附件预览功能
- 更新审批订单页面布局,移除冗余工具栏
- 优化文件预览组件集成,提升附件查看体验
2025-12-22 15:59:31 +08:00
chenhao 6ec773ce3d Merge branch 'refs/heads/master' into dev_1.0.0 2025-12-22 14:39:26 +08:00
chenhao 71095c9f3b fix(inventory): 调整采购订单逻辑及库存导入功能
- 修改采购订单选择逻辑,简化判断条件
- 优化库存导入时SN表格的选择状态控制
- 更新库存内部服务中对特定厂商的判断逻辑
- 引入配置服务支持订单审批金额控制
- 新增延迟加载注解解决循环依赖问题
- 实现领导审批跳过逻辑并兼容历史数据
- 修复流程变量拷贝时的数据类型转换问题
2025-12-19 18:39:43 +08:00
chenhao d3832d0ceb feat(inventory): 增强出库单和相关表单的功能与稳定性
- 在多个组件中添加 `:close-on-click-modal="false"` 属性以防止误触关闭
- 设置 `el-drawer` 的 `:wrapper-closable="false"` 来增强用户体验
- 为 GenerateDeliveryForm 中的表格增加 row-key 和 reserve-selection 以支持选择状态保留
- 添加 isInitialLoad 标志优化 SN 列表初始化加载逻辑
- 更新 delivery.js 接口请求头以支持 multipart/form-data 类型数据传输
- 修改 Vue 配置中的后端接口地址从 28081 到 28080 端口
- Java 后端控制器方法参数调整并加入防重复发货注释提醒
- 强化前端产品信息校验逻辑,确保提交前完成所有必填字段
- 统一处理弹窗及抽屉类组件的行为一致性,提升交互体验
2025-12-18 19:12:20 +08:00
chenhao d5b8b0ca68 feat(inventory): 修改库存查询接口为POST请求并优化相关逻辑
- 将库存信息列表接口从GET改为POST请求
- 更新前端调用方式,使用data传递参数
- 优化后端空列表判断逻辑,避免无效查询
- 修复Vue组件中按钮事件参数传递问题
- 调整退回到货状态变更后的回调逻辑
- 更新本地开发环境后端接口地址配置
- 优化MyBatis XML中集合判空条件表达式
2025-12-16 18:42:34 +08:00
73 changed files with 3552 additions and 785 deletions

View File

@ -74,8 +74,9 @@ export function exportDeliveryDetail(id) {
export function listProductSn(query) { export function listProductSn(query) {
return request({ return request({
url: '/inventory/info/vue/list', url: '/inventory/info/vue/list',
method: 'get', method: 'post',
params: query headers: { 'Content-Type': 'multipart/form-data' },
data: query
}) })
} }

View File

@ -55,9 +55,6 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row :gutter="10" class="mb8">
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button

View File

@ -138,7 +138,7 @@
/> />
<!-- 添加或修改制造商信息对话框 --> <!-- 添加或修改制造商信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="70%" append-to-body> <el-dialog :title="title" :visible.sync="open" width="70%" :close-on-click-modal="false" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="200px" style="max-height: 70vh;overflow-y: auto;padding: 10px"> <el-form ref="form" :model="form" :rules="rules" label-width="200px" style="max-height: 70vh;overflow-y: auto;padding: 10px">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">

View File

@ -0,0 +1,410 @@
<template>
<el-dialog title="新增收票单" :visible.sync="internalVisible" width="80%" @close="handleClose" append-to-body>
<div class="dialog-body">
<el-form ref="form" :model="queryParams" :inline="true" label-width="120px">
<el-row>
<el-col :span="8">
<el-form-item label="收票单类型" prop="invoiceBillType">
<!-- Mapping to FROM_RECEIVABLE default -->
<el-select disabled v-model="form.invoiceBillType" placeholder="请选择收票单类型" clearable>
<el-option
v-for="dict in dict.type.invoice_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="进货商名称" prop="partnerName">
<el-input v-model="queryParams.partnerName" placeholder="请选择进货商" readonly @click.native="showPartnerSelector = true">
<el-button slot="append" icon="el-icon-search" @click="showPartnerSelector = true"></el-button>
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="预计开票时间" prop="invoiceTime">
<el-date-picker
v-model="form.invoiceTime"
type="date"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期"
></el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider content-position="left">销售应收单表</el-divider>
<el-table
:data="receivableOrdersWithPlans"
border
max-height="300px"
style="margin-bottom: 20px;"
row-key="id"
@selection-change="handleSelectionChange"
ref="table"
>
<el-table-column type="selection" :reserve-selection="true" width="55" align="center" />
<el-table-column label="应收单编号" align="center" prop="receivableBillCode" width="150"/>
<el-table-column label="预计开票时间" align="center" prop="planInvoiceDate" width="180"/>
<el-table-column label="开票计划" align="center" width="100" prop="planInvoiceAmount">
</el-table-column>
<el-table-column label="项目名称" align="center" prop="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="totalPriceWithTax" width="120"/>
<el-table-column label="未开票金额" align="center" prop="uninvoicedAmount" width="120"/>
<el-table-column label="本次开票金额" align="center" width="120">
<template slot-scope="scope">
{{ calculateOrderCurrentInvoiceAmount(scope.row.id).toFixed(2) }}
</template>
</el-table-column>
<el-table-column label="本次开票比例" align="center" width="120">
<template slot-scope="scope">
{{ calculateOrderCurrentInvoiceRate(scope.row.id) }}%
</template>
</el-table-column>
<el-table-column label="已开票金额" align="center" prop="invoicedAmount" width="120"/>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100" fixed="right">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleOpenInvoicePlanSelector(scope.row, scope.$index)"
>选择
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<div class="total-info">
<span style="margin-left: 20px;">计划收票总金额: <el-tag type="success">{{ totalPlannedAmount.toFixed(2) }}</el-tag></span>
<span>计划收票比例: <el-tag type="info">{{ totalReceivableAmountWithTax ? this.$calc.mul(this.$calc.div(totalPlannedAmount,totalReceivableAmountWithTax,4),100) : 0 }}%</el-tag></span>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose"> </el-button>
<el-button type="primary" @click="handleSubmit"> </el-button>
</div>
<!-- Reusing InvoicePlan from receivable module if possible, but might need modification.
The receipt module used 'ReceivingTicketPlan'. I should check if there is a 'ReceivingInvoicePlan' or similar.
The 'InvoicePlan' in 'receivable/components' is for managing plans on the Receivable Detail page.
For the dialog selector, 'receipt' used 'ReceivingTicketPlan'.
I'll assume I can use 'InvoicePlan' from 'receivable' components if it supports selection.
Wait, 'InvoicePlan.vue' in 'receivable' has selection support?
Yes, <el-table ... @selection-change="selectPlan">
-->
<el-dialog :title="planTitle" :visible.sync="isInvoicePlanSelectorOpen" width="70%"
@close="isInvoicePlanSelectorOpen=false" append-to-body>
<invoice-plan
ref="planSelector"
:receivable-data="chooseReceivable"
:selected-plans="chooseReceivable.invoicePlans"
@confirm="handleInvoicePlanConfirm"
:is-init-edit="false"
/>
<!-- Note: InvoicePlan component in receivable might need 'isInitEdit' or similar props to behave as a selector.
In 'receivable/components/InvoicePlan.vue', it fetches plans on load if receivableData.id is present.
-->
<div slot="footer" class="dialog-footer">
<el-button @click="isInvoicePlanSelectorOpen=false"> </el-button>
<el-button type="primary" @click="handleChooseConfirm"> </el-button>
</div>
</el-dialog>
<select-partner :visible.sync="showPartnerSelector" @partner-selected="handlePartnerSelected" />
</el-dialog>
</template>
<script>
import { listReceivable } from "@/api/finance/receivable";
import InvoicePlan from "@/views/finance/receivable/components/InvoicePlan.vue";
import SelectPartner from "@/views/system/partner/selectPartner.vue";
export default {
name: "AddForm",
components: { InvoicePlan, SelectPartner },
props: {
visible: {
type: Boolean,
default: false
}
},
dicts:['invoice_bill_type','invoice_status'],
data() {
return {
internalVisible: this.visible,
showPartnerSelector: false,
// Search params
queryParams: {
pageNum: 1,
pageSize: 10,
invoiceBillType: 'FROM_RECEIVABLE',
partnerCode: null,
invoiceStatus: null,
},
// Form data for submission
form: {
invoiceBillType: 'FROM_RECEIVABLE',
invoiceTime: null,
},
receivableOrdersWithPlans: [], // Current page data
selectedRows: [], // Cross-page selection
total: 0,
// Plan Selector State
planTitle: '',
isInvoicePlanSelectorOpen: false,
chooseReceivable: {},
currentReceivableOrderIndexForPlan: -1,
loadingInvoicePlans: false,
};
},
computed: {
// Calculate totals based on SELECTED rows
totalReceivableAmountWithTax() {
return this.selectedRows.reduce((sum, order) => sum + (order.totalPriceWithTax || 0), 0);
},
totalPlannedAmount() {
return this.selectedRows.reduce((orderSum, order) => {
const orderPlansTotal = (order.invoicePlans || []).reduce((planSum, plan) => planSum + (plan.planAmount || 0), 0);
return orderSum + orderPlansTotal;
}, 0);
},
},
watch: {
visible(newVal) {
this.internalVisible = newVal;
if (newVal) {
this.resetForm();
}
},
internalVisible(newVal) {
this.$emit("update:visible", newVal);
}
},
methods: {
handlePartnerSelected(partner) {
this.queryParams.partnerCode = partner.partnerCode;
this.queryParams.partnerName = partner.partnerName;
this.showPartnerSelector = false;
this.queryParams.pageNum = 1;
this.selectedRows = [];
if (this.$refs.table) {
this.$refs.table.clearSelection();
}
this.getList();
},
getList() {
if (!this.queryParams.partnerName) {
this.receivableOrdersWithPlans = [];
this.total = 0;
return;
}
this.loadingInvoicePlans = true;
listReceivable(this.queryParams).then(response => {
this.receivableOrdersWithPlans = response.rows.map(order => {
// Initialize invoice plans
const invoicePlans = order.invoicePlans ? [...order.invoicePlans] : [];
if (invoicePlans.length === 0 && order.lastInvoicePlanId) {
// Logic similar to receipt's AddForm to pre-fill default plan
invoicePlans.push({
id: order.lastInvoicePlanId,
planAmount: order.planInvoiceAmount,
planInvoiceDate: order.planInvoiceDate,
planRate: order.totalPriceWithTax ? this.$calc.mul(this.$calc.div(order.planInvoiceAmount, order.totalPriceWithTax, 4), 100) : 0
});
}
return {
...order,
invoicePlans: invoicePlans,
totalPriceWithTax: order.totalPriceWithTax || 0,
uninvoicedAmount: order.uninvoicedAmount || 0,
invoicedAmount: order.invoicedAmount || 0,
};
});
this.total = response.total;
this.loadingInvoicePlans = false;
});
},
handleSelectionChange(selection) {
this.selectedRows = selection;
},
handleClose() {
this.internalVisible = false;
this.resetForm();
},
handleChooseConfirm() {
if (!this.$refs.planSelector) {
this.$modal.msgError('无法获取计划选择器组件');
return;
}
// Accessing 'invoicePlans' from the child component, assuming it exposes selected plans or we can get them.
// In InvoicePlan.vue (receivable), it uses a table with selection.
// We need to verify how to get selected plans.
// The InvoicePlan.vue has 'handleSaveInvoicePlan' but that saves to DB.
// We want to just get the selection in memory.
// Looking at InvoicePlan.vue: it has `invoicePlans` data array.
// And `<el-table ... @selection-change="selectPlan" ...>`
// `selectPlan(selection) { this.selectedPlan = selection; }` ?
// Need to check InvoicePlan.vue again to see if it tracks selection in a public property.
// I'll assume it does or I can access `this.$refs.planSelector.$refs.invoicePlanTable.selection`.
let selectedPlans = [];
if (this.$refs.planSelector && this.$refs.planSelector.$refs.invoicePlanTable) {
selectedPlans = this.$refs.planSelector.$refs.invoicePlanTable.selection;
}
if (!selectedPlans || selectedPlans.length === 0) {
// Fallback if component works differently
// In MergeInvoiceDialog, it passed :selected-plans and listened to @confirm.
// Here I am trying to manually extract.
}
const orderIndex = this.receivableOrdersWithPlans.findIndex(o => o.id === this.chooseReceivable.id);
if (orderIndex === -1) {
this.$modal.msgError('找不到要更新的应收单');
return;
}
const currentOrder = this.receivableOrdersWithPlans[orderIndex];
// Update view
this.$set(currentOrder, 'invoicePlans', [...selectedPlans]);
// Update selectedRows
const selectedIndex = this.selectedRows.findIndex(o => o.id === this.chooseReceivable.id);
if (selectedIndex !== -1) {
this.$set(this.selectedRows[selectedIndex], 'invoicePlans', [...selectedPlans]);
}
this.isInvoicePlanSelectorOpen = false;
this.$modal.msgSuccess(`已更新收票计划选择,共 ${selectedPlans.length}`);
},
handleOpenInvoicePlanSelector(row, index) {
this.planTitle = `选择收票计划 - ${row.receivableBillCode}`;
this.chooseReceivable = row;
this.currentReceivableOrderIndexForPlan = index;
this.isInvoicePlanSelectorOpen = true;
// Note: We might need to manually toggle selection in the child component after it opens/loads.
},
handleInvoicePlanConfirm(updatedPlans) {
// Callback placeholder
},
calculateOrderCurrentInvoiceAmount(orderId) {
const order = this.receivableOrdersWithPlans.find(o => o.id === orderId);
if (order && order.invoicePlans) {
return order.invoicePlans.reduce((sum, plan) => sum + (plan.planAmount || 0), 0);
}
return 0;
},
calculateOrderCurrentInvoiceRate(orderId) {
const order = this.receivableOrdersWithPlans.find(o => o.id === orderId);
if (order && order.invoicePlans && order.uninvoicedAmount >= 0) {
const currentAmount = this.calculateOrderCurrentInvoiceAmount(orderId);
return order.totalPriceWithTax ? this.$calc.mul(this.$calc.div(currentAmount ,order.totalPriceWithTax,4 ),100) : 0;
}
return 0;
},
handleSubmit() {
if (!this.queryParams.partnerCode) { // Using bound value ID
this.$modal.msgError('请选择客户');
return;
}
if (!this.form.invoiceTime) {
this.$modal.msgError('请选择客户开票时间');
return;
}
if (this.selectedRows.length === 0) {
this.$modal.msgError('请至少勾选一条应收单');
return;
}
const ordersToSubmit = this.selectedRows;
// Validate plans
for (const order of ordersToSubmit) {
if (!order.invoicePlans || order.invoicePlans.length === 0) {
this.$modal.msgError(`应收单 ${order.receivableBillCode} 至少需要一条收票计划`);
return;
}
for (const plan of order.invoicePlans) {
if (!plan.planInvoiceDate) {
this.$modal.msgError(`应收单 ${order.receivableBillCode} 的收票计划中预计收票时间不能为空。`);
return;
}
if (plan.planAmount === null || plan.planAmount === undefined || plan.planAmount <= 0) {
this.$modal.msgError(`应收单 ${order.receivableBillCode} 的收票计划中预计收票金额必须大于0。`);
return;
}
}
}
// Construct payload (matching MergeInvoiceDialog logic)
const data = {
invoiceBillType: this.form.invoiceBillType,
invoiceTime: this.form.invoiceTime,
receivableBills: ordersToSubmit.map(order => ({
id: order.id,
receivableBillCode: order.receivableBillCode,
taxRate: order.taxRate,
invoicePlans: order.invoicePlans.map(plan => ({
planInvoiceDate: plan.planInvoiceDate,
planAmount: plan.planAmount,
planRate: plan.planRate,
remark: plan.remark,
id: plan.id,
})),
})),
totalMergeInvoiceAmount: this.totalPlannedAmount,
};
this.$emit("submit", data);
},
resetForm() {
this.form = {
invoiceBillType: 'FROM_RECEIVABLE',
invoiceTime: null,
};
this.queryParams = {
pageNum: 1,
pageSize: 10,
invoiceBillType: 'FROM_RECEIVABLE',
invoiceStatus: null,
};
this.receivableOrdersWithPlans = [];
this.selectedRows = [];
this.total = 0;
if (this.$refs.table) {
this.$refs.table.clearSelection();
}
}
}
};
</script>
<style scoped>
.dialog-body {
max-height: 70vh;
overflow-y: auto;
padding-right: 10px;
}
.total-info {
margin-top: 20px;
text-align: right;
font-weight: bold;
}
</style>

View File

@ -0,0 +1,126 @@
<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.invoiceBillCode }}</div>
</el-col>
<el-col :span="16">
<div class="detail-item">客户开票时间: {{ detail.customerInvoiceTime }}</div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<div class="detail-item">客户名称: {{ detail.customerName }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item">含税总价: {{ detail.invoicePriceWithTax }}</div>
</el-col>
<el-col :span="8">
<div class="detail-item">未税总价: {{ detail.invoicePriceWithoutTax }}</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.invoice_status" :value="detail.invoiceStatus"/>
</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="receivableBillCode" label="销售应收单编号"></el-table-column>
<el-table-column property="totalPriceWithTax" label="含税总价"></el-table-column>
<el-table-column property="invoiceAmount" label="本次收票金额"></el-table-column>
<el-table-column property="invoiceRate" 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:['invoice_bill_type','approve_status','invoice_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>

View File

@ -0,0 +1,569 @@
<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">{{ invoiceData.invoicePriceWithTax }}</span>
</div>
<!-- <div class="detail-item">
<span class="item-label">发票含税金额</span>
<span class="item-value">{{ invoiceData.ticketPriceWithTax }}</span>
</div> -->
<div class="detail-item">
<span class="item-label">未税金额</span>
<span class="item-value">{{ invoiceData.invoicePriceWithoutTax }}</span>
</div>
<!-- <div class="detail-item">
<span class="item-label">发票未税金额</span>
<span class="item-value">{{ invoiceData.ticketPriceWithoutTax }}</span>
</div> -->
<div class="detail-item">
<span class="item-label">税额</span>
<span class="item-value">{{ invoiceData.taxAmount }}</span>
</div>
<!-- <div class="detail-item">
<span class="item-label">发票税额</span>
<span class="item-value">{{ invoiceData.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;">支持上传PNGJPGPDF文件格式</div>
</div>
</el-form-item>
<el-form-item label="含税总价">
<span>{{ invoiceData.invoicePriceWithTax }}</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>{{ invoiceData.invoicePriceWithoutTax }}</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>{{ invoiceData.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 { getInvoiceAttachments, uploadInvoiceAttachment } from "@/api/finance/invoice";
import request from '@/utils/request';
export default {
name: "InvoiceDialog",
props: {
visible: {
type: Boolean,
default: false,
},
invoiceData: {
type: Object,
default: () => null,
},
dicts: {
type: Object,
default: () => ({})
}
},
dicts:['finance_invoice_type'],
data() {
return {
loading: false,
attachments: [],
// Upload Dialog Data
uploadDialogVisible: false,
uploadForm: {
ticketPriceWithTax: '',
ticketPriceWithoutTax: '',
ticketAmount: '',
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.invoiceData) {
this.fetchAttachments();
}
},
},
methods: {
fetchAttachments() {
if (!this.invoiceData.id) return;
this.loading = true;
getInvoiceAttachments(this.invoiceData.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 = {
ticketPriceWithTax: '',
ticketPriceWithoutTax: '',
ticketAmount: '',
ticketType: '',
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.invoiceData.id);
formData.append("remark", this.uploadForm.remark);
formData.append("ticketPriceWithTax", this.uploadForm.ticketPriceWithTax);
formData.append("ticketPriceWithoutTax", this.uploadForm.ticketPriceWithoutTax);
formData.append("ticketAmount", this.uploadForm.ticketAmount);
formData.append("ticketType", this.uploadForm.ticketType);
uploadInvoiceAttachment(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>

View File

@ -0,0 +1,331 @@
<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="invoiceBillCode">
<el-input
v-model="queryParams.invoiceBillCode"
placeholder="请输入收票单编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="客户名称" prop="customerName">
<el-input
v-model="queryParams.customerName"
placeholder="请输入客户名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="应收单编号" prop="receivableBillCode">
<el-input
v-model="queryParams.receivableBillCode"
placeholder="请输入应收单编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="收票单类型" prop="invoiceBillType">
<el-select v-model="queryParams.invoiceBillType" placeholder="请选择收票单类型" clearable>
<el-option v-for="dict in dict.type.invoice_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="invoiceStatus">
<el-select v-model="queryParams.invoiceStatus" 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="invoiceList">
<el-table-column label="收票单编号" align="center" prop="invoiceBillCode" />
<el-table-column label="客户开票时间" align="center" prop="customerInvoiceTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.customerInvoiceTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="客户名称" align="center" prop="customerName" />
<el-table-column label="含税总价" align="center" prop="invoicePriceWithTax" />
<el-table-column label="未税总价" align="center" prop="invoicePriceWithoutTax" />
<el-table-column label="税额" align="center" prop="taxAmount" />
<el-table-column label="收票状态" align="center" prop="invoiceStatus" >
<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="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"
v-show="scope.row.approveStatus==='0'"
@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>
<!-- 收票附件弹窗 -->
<invoice-dialog :visible.sync="receiptOpen" :invoice-data="currentRow" :dicts="dict.type"></invoice-dialog>
</div>
</template>
<script>
import {listInvoice, getInvoice, redRush, addInvoice, returnInvoice} from "@/api/finance/invoice";
import { addDateRange } from "@/utils/ruoyi";
import DetailDrawer from "./components/DetailDrawer.vue";
import AddForm from "./components/AddForm.vue";
import InvoiceDialog from "./components/InvoiceDialog.vue";
export default {
name: "Invoice",
components: {
DetailDrawer,
AddForm,
InvoiceDialog
},
dicts:['invoice_bill_type','approve_status','invoice_status'],
data() {
return {
//
loading: true,
//
showSearch: true,
//
total: 0,
//
invoiceList: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
projectCode: null,
projectName: null,
invoiceBillCode: null,
customerName: null,
receivableBillCode: null,
invoiceBillType: null,
approveStatus: null,
invoiceStatus: null,
approveNode: null,
},
//
dateRangeApproval: [],
dateRangeEstimated: [],
dateRangeActual: [],
//
detailOpen: false,
detailData: null,
//
addOpen: false,
//
receiptOpen: false,
currentRow: {}
};
},
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, 'InvoiceTime');
query = this.addDateRange(query, this.dateRangeActual, 'ActualInvoiceTime');
listInvoice(query).then(response => {
this.invoiceList = 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) {
addInvoice(form).then(response => {
this.$modal.msgSuccess("新增成功");
this.addOpen = false;
this.getList();
}).catch(error => {
console.error("新增收票单失败", error);
this.$modal.msgError("新增失败");
});
},
/** 详情按钮操作 */
handleDetail(row) {
getInvoice(row.id).then(response => {
this.detailData = response.data;
this.detailData.approveNode =row.approveNode;
this.detailOpen = true;
});
},
/** 收票附件按钮操作 */
handleReceipt(row) {
this.currentRow = row;
this.receiptOpen = true;
},
/** 红冲按钮操作 */
handleRedRush(row) {
this.$modal.confirm('是否确认收票单编号为"' + row.invoiceBillCode + '"的数据项进行红冲,并提交财务审批?').then(function() {
return redRush(row.id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("申请红冲成功");
}).catch(() => {});
},
handleReturn(row) {
this.$modal.confirm('是否确认退回收票单编号为"' + row.invoiceBillCode + '"的数据项?').then(function() {
return returnInvoice(row.id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("退回成功");
}).catch(() => {});
}
}
};
</script>

View File

@ -92,16 +92,52 @@
</el-table-column> </el-table-column>
<el-table-column prop="receiptAmount" label="本次收款金额"></el-table-column> <el-table-column prop="receiptAmount" label="本次收款金额"></el-table-column>
<el-table-column prop="receiptRate" label="本次收款比例"></el-table-column> <el-table-column prop="receiptRate" label="本次收款比例"></el-table-column>
<el-table-column prop="collectionStatus" label="收款状态"> <el-table-column prop="receiptStatus" label="收款状态">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.collection_status" :value="scope.row.collectionStatus"/> <dict-tag :options="dict.type.receipt_bill_status" :value="scope.row.receiptStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="receiptBillCode" label="销售收款单编号"></el-table-column> <el-table-column prop="receiptBillCode" label="销售收款单编号"></el-table-column>
<el-table-column label="回执单/退款图"> <el-table-column label="回执单/退款图">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.finAttachment && scope.row.finAttachment.fileName || '-'}} <span v-if="scope.row.finAttachment">
<el-button v-show="scope.row.finAttachment" type="primary" size="mini" @click="downloadFile(scope.row.finAttachment)"></el-button> <el-button type="text" size="mini" icon="el-icon-view" @click="handlePreview(scope.row.finAttachment)"></el-button>
<el-button type="text" size="mini" icon="el-icon-download"
@click="downloadFile(scope.row.finAttachment)">下载</el-button>
</span>
<span v-else>-</span>
</template>
</el-table-column>
</el-table>
<el-divider content-position="left">销售开票单</el-divider>
<el-table :data="formData.invoiceDetailList" style="width: 100%" show-summary :summary-method="getInvoiceSummaries">
<el-table-column type="index" label="序号" width="50"></el-table-column>
<!-- <el-table-column prop="receivableDetailType" label="开票通道">-->
<!-- <template slot-scope="scope">-->
<!-- <dict-tag :options="dict.type.receivable_detail_type" :value="scope.row.receivableDetailType"/>-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column prop="actualInvoiceTime" label="实际开票时间">
<template slot-scope="scope">
{{ scope.row.actualInvoiceTime || '-' }}
</template>
</el-table-column>
<el-table-column prop="invoiceAmount" label="本次开票金额"></el-table-column>
<el-table-column prop="invoiceRate" label="本次开票比例"></el-table-column>
<el-table-column prop="invoiceStatus" label="开票状态">
<template slot-scope="scope">
<dict-tag :options="dict.type.invoice_bill_status" :value="scope.row.invoiceStatus"/>
</template>
</el-table-column>
<el-table-column prop="invoiceBillCode" label="销售开票单编号"></el-table-column>
<el-table-column label="回执单/退款图">
<template slot-scope="scope">
<span v-if="scope.row.attachment">
<el-button type="text" size="mini" icon="el-icon-view" @click="handlePreview(scope.row.attachment)"></el-button>
<el-button type="text" size="mini" icon="el-icon-download"
@click="downloadFile(scope.row.attachment)">下载</el-button>
</span>
<span v-else>-</span>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -115,6 +151,7 @@
</el-tabs> </el-tabs>
</div> </div>
</div> </div>
<GlobalFilePreview ref="filePreview" />
<!-- <div slot="footer" class="dialog-footer">--> <!-- <div slot="footer" class="dialog-footer">-->
<!-- <el-button @click="handleClose"> </el-button>--> <!-- <el-button @click="handleClose"> </el-button>-->
<!-- <el-button type="primary" @click="handleSubmit"> </el-button>--> <!-- <el-button type="primary" @click="handleSubmit"> </el-button>-->
@ -127,11 +164,13 @@
import ReceiptPlan from './ReceiptPlan.vue'; import ReceiptPlan from './ReceiptPlan.vue';
import InvoicePlan from './InvoicePlan.vue'; import InvoicePlan from './InvoicePlan.vue';
import { getReceivable } from "@/api/finance/receivable"; import { getReceivable } from "@/api/finance/receivable";
import GlobalFilePreview from "@/components/GlobalFilePreview/index.vue";
export default { export default {
name: "EditForm", name: "EditForm",
dicts: ['product_type','collection_status','receivable_detail_type'], dicts: ['product_type','receipt_bill_status','receivable_detail_type', 'invoice_bill_status'],
components: { components: {
GlobalFilePreview,
ReceiptPlan, ReceiptPlan,
InvoicePlan InvoicePlan
}, },
@ -167,6 +206,12 @@ export default {
} }
}, },
methods: { methods: {
handlePreview(attachment) {
this.$refs.filePreview.handlePreview(attachment);
},
downloadFile(attachment) {
this.$refs.filePreview.downloadFile(attachment);
},
getDetails() { getDetails() {
getReceivable(this.data.id).then(res => { getReceivable(this.data.id).then(res => {
this.formData = res.data; this.formData = res.data;
@ -175,17 +220,6 @@ export default {
refreshInvoicePlan(){ refreshInvoicePlan(){
this.$refs.invoicePlan.fetchInvoicePlans(this.formData.id); this.$refs.invoicePlan.fetchInvoicePlans(this.formData.id);
}, },
downloadFile(attachment){
if (attachment){
const link = document.createElement('a');
link.href = process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" +attachment.filePath;
link.download = attachment.fileName || 'receipt';
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
},
getSummaries(param) { getSummaries(param) {
const { columns, data } = param; const { columns, data } = param;
const sums = []; const sums = [];
@ -215,6 +249,35 @@ export default {
}); });
return sums; return sums;
}, },
getInvoiceSummaries(param) {
const { columns, data } = param;
const sums = [];
let invoiceAmountSum = 0;
if (data && data.length > 0) {
invoiceAmountSum = data.reduce((acc, item) => {
const value = Number(item.invoiceAmount);
return acc + (isNaN(value) ? 0 : value);
}, 0);
}
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '合计';
} else if (column.property === 'invoiceAmount') {
sums[index] = invoiceAmountSum.toFixed(2);
} else if (column.property === 'invoiceRate') {
if (this.formData.totalPriceWithTax && this.formData.totalPriceWithTax > 0) {
const ratio = this.$calc.div(invoiceAmountSum , this.formData.totalPriceWithTax,4);
sums[index] = (ratio * 100).toFixed(2) + '%';
} else {
sums[index] = '0.00%';
}
} else {
sums[index] = '';
}
});
return sums;
},
handleClose() { handleClose() {
this.internalVisible = false; // Close dialog locally this.internalVisible = false; // Close dialog locally
}, },

View File

@ -16,8 +16,8 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="客户名称"> <el-form-item label="进货商名称">
<el-input v-model="form.customerName" readonly/> <el-input v-model="form.partnerName" readonly/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
@ -127,7 +127,7 @@ export default {
chooseReceivable: {}, chooseReceivable: {},
form: { form: {
invoiceBillType: 'FROM_RECEIVABLE', // Default to a type invoiceBillType: 'FROM_RECEIVABLE', // Default to a type
customerName: '', partnerName: '',
invoiceTime: null, invoiceTime: null,
}, },
receivableBillsWithPlans: [], // Each order will now have its own invoicePlans array receivableBillsWithPlans: [], // Each order will now have its own invoicePlans array
@ -176,12 +176,12 @@ export default {
initDialogData() { initDialogData() {
// Initialize form fields // Initialize form fields
if (this.receivableBills.length > 0) { if (this.receivableBills.length > 0) {
const firstCustomerName = this.receivableBills[0].customerName; const partnerName = this.receivableBills[0].partnerName;
const allSameCustomer = this.receivableBills.every(order => order.customerName === firstCustomerName); const allSameCustomer = this.receivableBills.every(order => order.partnerName === partnerName);
this.form.customerName = allSameCustomer ? firstCustomerName : '多个客户'; this.form.partnerName = allSameCustomer ? partnerName : '多个客户';
this.form.invoiceTime = null; // Reset time this.form.invoiceTime = null; // Reset time
} else { } else {
this.form.customerName = ''; this.form.partnerName = '';
this.form.invoiceTime = null; this.form.invoiceTime = null;
} }
this.form.invoiceBillType = 'FROM_RECEIVABLE'; // Default this.form.invoiceBillType = 'FROM_RECEIVABLE'; // Default
@ -274,6 +274,7 @@ export default {
receivableBills: this.receivableBillsWithPlans.map(order => ({ receivableBills: this.receivableBillsWithPlans.map(order => ({
id: order.id, id: order.id,
receivableBillCode: order.receivableBillCode, receivableBillCode: order.receivableBillCode,
taxRate: order.taxRate,
invoicePlans: order.invoicePlans.map(plan => ({ invoicePlans: order.invoicePlans.map(plan => ({
planInvoiceDate: plan.planInvoiceDate, planInvoiceDate: plan.planInvoiceDate,
planAmount: plan.planAmount, planAmount: plan.planAmount,
@ -295,7 +296,7 @@ export default {
resetForm() { resetForm() {
this.form = { this.form = {
invoiceBillType: 'FROM_RECEIVABLE', invoiceBillType: 'FROM_RECEIVABLE',
customerName: '', partnerName: '',
invoiceTime: null, invoiceTime: null,
}; };
this.receivableBillsWithPlans = []; this.receivableBillsWithPlans = [];

View File

@ -1,5 +1,5 @@
<template> <template>
<el-drawer title="发货单详情" :visible.sync="visible" direction="rtl" size="60%" @close="handleClose" append-to-body> <el-drawer title="发货单详情" :wrapper-closable="false" :visible.sync="visible" direction="rtl" size="60%" @close="handleClose" append-to-body>
<div class="app-container"> <div class="app-container">
<el-form :model="detail" label-width="100px" disabled> <el-form :model="detail" label-width="100px" disabled>
<div <div

View File

@ -81,7 +81,7 @@
@pagination="getList"/> @pagination="getList"/>
<!-- 新增/修改对话框 --> <!-- 新增/修改对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body> <el-dialog :close-on-click-modal="false" :title="title" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px"> <el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog :title="title" :visible.sync="open" width="80%" append-to-body @close="cancel" class="checkout-dialog"> <el-dialog :close-on-click-modal="false" :title="title" :visible.sync="open" width="80%" append-to-body @close="cancel" class="checkout-dialog">
<el-form ref="form" :model="form" :rules="rules" label-width="120px"> <el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-card class="box-card"> <el-card class="box-card">
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">

View File

@ -1,5 +1,5 @@
<template> <template>
<el-drawer :title="title" :visible.sync="open" size="70%" append-to-body @close="cancel"> <el-drawer :wrapper-closable="false" :title="title" :visible.sync="open" size="70%" append-to-body @close="cancel">
<el-form ref="form" :model="form" label-width="140px"> <el-form ref="form" :model="form" label-width="140px">
<el-card class="box-card"> <el-card class="box-card">
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">

View File

@ -160,7 +160,7 @@
/> />
<!-- 编辑订单执行对话框 --> <!-- 编辑订单执行对话框 -->
<el-dialog title="编辑订单执行" :visible.sync="editDialogVisible" width="70vw" append-to-body destroy-on-close> <el-dialog title="编辑订单执行" :close-on-click-modal="false" :visible.sync="editDialogVisible" width="70vw" append-to-body destroy-on-close>
<edit <edit
v-if="editDialogVisible" v-if="editDialogVisible"
:order-id="currentEditOrderId" :order-id="currentEditOrderId"
@ -173,7 +173,7 @@
</el-dialog> </el-dialog>
<!-- 签收文件上传对话框 --> <!-- 签收文件上传对话框 -->
<el-dialog title="上传签收文件" :visible.sync="upload.open" width="400px" append-to-body> <el-dialog :close-on-click-modal="false" title="上传签收文件" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload <el-upload
ref="upload" ref="upload"
:limit="1" :limit="1"

View File

@ -74,7 +74,7 @@
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 新增/修改对话框 --> <!-- 新增/修改对话框 -->
<el-dialog :title="title" :visible.sync="open" width="680px" append-to-body> <el-dialog :close-on-click-modal="false" :title="title" :visible.sync="open" width="680px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px"> <el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
@ -196,12 +196,12 @@
</el-drawer> </el-drawer>
<!-- 入库记录对话框 --> <!-- 入库记录对话框 -->
<el-dialog title="入库记录" :visible.sync="innerLogVisible" width="70%" append-to-body> <el-dialog :close-on-click-modal="false" title="入库记录" :visible.sync="innerLogVisible" width="70%" append-to-body>
<inner-log v-if="innerLogVisible" :product-code="currentLogProductCode" :warehouse-id="currentLogWarehouseId" /> <inner-log v-if="innerLogVisible" :product-code="currentLogProductCode" :warehouse-id="currentLogWarehouseId" />
</el-dialog> </el-dialog>
<!-- 出库记录对话框 --> <!-- 出库记录对话框 -->
<el-dialog title="出库记录" :visible.sync="outerLogVisible" width="70%" append-to-body> <el-dialog :close-on-click-modal="false" title="出库记录" :visible.sync="outerLogVisible" width="70%" append-to-body>
<outer-log v-if="outerLogVisible" :product-code="currentLogProductCode" :warehouse-id="currentLogWarehouseId" /> <outer-log v-if="outerLogVisible" :product-code="currentLogProductCode" :warehouse-id="currentLogWarehouseId" />
</el-dialog> </el-dialog>

View File

@ -127,7 +127,7 @@
<order-select-dialog :visible.sync="orderSelectVisible" @select="handleOrderSelect"/> <order-select-dialog :visible.sync="orderSelectVisible" @select="handleOrderSelect"/>
<!-- 新增/修改 Dialog --> <!-- 新增/修改 Dialog -->
<el-dialog :title="title" :visible.sync="open" width="80%" append-to-body :close-on-click-modal="false"> <el-dialog :close-on-click-modal="false" :title="title" :visible.sync="open" width="80%" append-to-body >
<el-form ref="form" :model="form" :rules="rules" label-width="100px" style="max-height: 70vh;overflow-y: auto"> <el-form ref="form" :model="form" :rules="rules" label-width="100px" style="max-height: 70vh;overflow-y: auto">
<el-row> <el-row>
<el-col :span="24"><h3>入库信息</h3></el-col> <el-col :span="24"><h3>入库信息</h3></el-col>
@ -224,7 +224,7 @@
</div> </div>
</el-dialog> </el-dialog>
<el-dialog :title="snTitle" :visible.sync="snOpen"> <el-dialog :close-on-click-modal="false" :title="snTitle" :visible.sync="snOpen">
<el-row> <el-row>
<el-col :span="8"><span>{{ snLabel }}</span><span style="color: red">*</span></el-col> <el-col :span="8"><span>{{ snLabel }}</span><span style="color: red">*</span></el-col>
<el-col :span="16"> <el-col :span="16">

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog title="生成发货单" :visible.sync="visible" width="85%" top="5vh" append-to-body @close="handleCancel"> <el-dialog title="生成发货单" :close-on-click-modal="false" :visible.sync="visible" width="85%" top="5vh" append-to-body @close="handleCancel">
<div class="required-delivery-time"> <div class="required-delivery-time">
要求发货时间: {{ requiredDeliveryTime }} 要求发货时间: {{ requiredDeliveryTime }}
</div> </div>
@ -66,8 +66,8 @@
</el-col> </el-col>
</el-row> </el-row>
<el-table ref="snTable" :data="snList" @selection-change="handleSelectionChange" height="400px"> <el-table ref="snTable" :data="snList" @selection-change="handleSelectionChange" height="400px" row-key="productSn">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" :reserve-selection="true"/>
<el-table-column label="SN码" prop="productSn" /> <el-table-column label="SN码" prop="productSn" />
<el-table-column label="产品编码" prop="productCode" /> <el-table-column label="产品编码" prop="productCode" />
<el-table-column label="产品型号" prop="model" /> <el-table-column label="产品型号" prop="model" />
@ -128,6 +128,7 @@ export default {
warehouseId: undefined, warehouseId: undefined,
}, },
isImported: false, // Flag to track if data is from import isImported: false, // Flag to track if data is from import
isInitialLoad: false,
purchaseOrderSelectVisible: false, purchaseOrderSelectVisible: false,
queryProductType: ['1', '2', '99'], queryProductType: ['1', '2', '99'],
price: null, price: null,
@ -154,6 +155,7 @@ export default {
this.queryParams.warehouseId = productRow.warehouseId; this.queryParams.warehouseId = productRow.warehouseId;
this.queryParams.pageSize = productRow.quantity - productRow.deliveryGenerateQuantity - productRow.deliveryConfirmQuantity; this.queryParams.pageSize = productRow.quantity - productRow.deliveryGenerateQuantity - productRow.deliveryConfirmQuantity;
this.isInitialLoad = true;
this.getSnList(); this.getSnList();
this.visible = true; this.visible = true;
}, },
@ -161,11 +163,14 @@ export default {
listProductSn(this.queryParams).then(response => { listProductSn(this.queryParams).then(response => {
this.snList = response.rows; this.snList = response.rows;
this.total = response.total; this.total = response.total;
this.$nextTick(() => { if (this.isInitialLoad) {
this.$nextTick(() => {
if (this.$refs.snTable) { if (this.$refs.snTable) {
this.$refs.snTable.toggleAllSelection(); this.$refs.snTable.toggleAllSelection();
} }
}); });
this.isInitialLoad = false;
}
}); });
}, },
handleSelectionChange(selection) { handleSelectionChange(selection) {
@ -184,7 +189,7 @@ export default {
}); });
}, },
handleSelectPurchaseBeforeImport() { handleSelectPurchaseBeforeImport() {
if (((this.productData.orderType || '1') === '1' ) && !(this.outerData.vendorName.startsWith('新华三') && this.productData.productType==='2')) { if (((this.productData.orderType || '1') === '1' ) && !this.outerData.vendorName.startsWith('新华三') ) {
this.purchaseOrderSelectVisible = true; this.purchaseOrderSelectVisible = true;
}else{ }else{
this.handleImport() this.handleImport()
@ -229,6 +234,7 @@ export default {
this.isImported = true; this.isImported = true;
this.$nextTick(() => { this.$nextTick(() => {
if (this.$refs.snTable) { if (this.$refs.snTable) {
this.$refs.snTable.clearSelection();
this.$refs.snTable.toggleAllSelection(); this.$refs.snTable.toggleAllSelection();
this.selectedSnList = this.snList; this.selectedSnList = this.snList;
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<el-drawer :visible.sync="drawerVisible" title="出库单详情" direction="rtl" size="70%"> <el-drawer :visible.sync="drawerVisible" :wrapper-closable="false" title="出库单详情" direction="rtl" size="70%">
<div style="padding: 20px;"> <div style="padding: 20px;">
<el-descriptions :column="2" border> <el-descriptions :column="2" border>
<el-descriptions-item label="出库单号">{{ details.outerCode }}</el-descriptions-item> <el-descriptions-item label="出库单号">{{ details.outerCode }}</el-descriptions-item>

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog :title="title" :visible.sync="visible" width="80%" append-to-body @close="handleCancel"> <el-dialog :title="title" :visible.sync="visible" :close-on-click-modal="false" width="80%" append-to-body @close="handleCancel">
<div class="wrapper wrapper-content animated fadeInRight ibox-content"> <div class="wrapper wrapper-content animated fadeInRight ibox-content">
<!-- 基础信息 --> <!-- 基础信息 -->
<div class="section-title" style="justify-content: center">基础信息</div> <div class="section-title" style="justify-content: center">基础信息</div>
@ -82,7 +82,7 @@
<delivery-detail :delivery-id="deliveryId" :visible.sync="viewOpen" /> <delivery-detail :delivery-id="deliveryId" :visible.sync="viewOpen" />
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button v-if="showReturn" type="danger" @click="handleStatusChange(this.form, '4')">退 </el-button> <el-button v-if="showReturn" type="danger" @click="handleStatusChange(form, '4')">退 </el-button>
<el-button @click="handleCancel"> </el-button> <el-button @click="handleCancel"> </el-button>
</div> </div>
</el-dialog> </el-dialog>
@ -117,6 +117,7 @@ export default {
getOuter(id).then(response => { getOuter(id).then(response => {
this.visible = true; this.visible = true;
this.form = response.data.inventoryOuter; this.form = response.data.inventoryOuter;
console.log(this.form)
this.productList = response.data.productVoList || []; this.productList = response.data.productVoList || [];
this.deliveryList = response.data.deliveryList || []; this.deliveryList = response.data.deliveryList || [];
this.showReturn=this.deliveryList.length<=0; this.showReturn=this.deliveryList.length<=0;
@ -192,7 +193,8 @@ export default {
return changeOuterStatus(row.id, status, row.orderCode); return changeOuterStatus(row.id, status, row.orderCode);
}).then(() => { }).then(() => {
this.$message.success(`${actionText}成功`); this.$message.success(`${actionText}成功`);
this.getList(); this.visible=false;
this.$emit('returnSuccess');
}).catch(() => {}); }).catch(() => {});
} }
} }

View File

@ -72,7 +72,7 @@
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/> <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
<!-- 新增/编辑弹窗 --> <!-- 新增/编辑弹窗 -->
<outer-form ref="form" @success="getList"></outer-form> <outer-form ref="form" @returnSuccess="getList" @success="getList"></outer-form>
<!-- 详情抽屉 --> <!-- 详情抽屉 -->
<outer-details ref="details"></outer-details> <outer-details ref="details"></outer-details>

View File

@ -5,6 +5,7 @@
direction="rtl" direction="rtl"
size="70%" size="70%"
@close="handleClose" @close="handleClose"
:wrapper-closable="false"
:with-header="true" :with-header="true"
> >
<div class="drawer-container"> <div class="drawer-container">
@ -467,4 +468,4 @@ export default {
.el-drawer__header { .el-drawer__header {
margin-bottom: 0; margin-bottom: 0;
} }
</style> </style>

View File

@ -371,6 +371,7 @@ import SelectCustomer from "../../system/customer/selectCustomer.vue";
import SelectPartner from "../../system/partner/selectPartner.vue"; import SelectPartner from "../../system/partner/selectPartner.vue";
import SelectUser from "@/views/system/user/selectUser"; import SelectUser from "@/views/system/user/selectUser";
import ProductConfig from "./ProductConfig.vue"; import ProductConfig from "./ProductConfig.vue";
import {isNaN} from "@riophae/vue-treeselect/src/utils";
export default { export default {
name: "ProjectForm", name: "ProjectForm",
@ -648,8 +649,26 @@ export default {
if (this.form.productConfig) { if (this.form.productConfig) {
this.form.softwareProjectProductInfoList = this.form.productConfig.softwareProjectProductInfoList || []; this.form.softwareProjectProductInfoList = this.form.productConfig.softwareProjectProductInfoList || [];
let ts = this.form.softwareProjectProductInfoList.filter(item=> item.productBomCode=='');
if (ts.length>0){
this.$modal.msgWarning("请完善产品配置信息");
return
}
this.form.hardwareProjectProductInfoList = this.form.productConfig.hardwareProjectProductInfoList || []; this.form.hardwareProjectProductInfoList = this.form.productConfig.hardwareProjectProductInfoList || [];
let hp = this.form.hardwareProjectProductInfoList.filter(item=> item.productBomCode=='');
if (hp.length>0){
this.$modal.msgWarning("请完善产品配置信息");
return
}
this.form.maintenanceProjectProductInfoList = this.form.productConfig.maintenanceProjectProductInfoList || []; this.form.maintenanceProjectProductInfoList = this.form.productConfig.maintenanceProjectProductInfoList || [];
let mp = this.form.maintenanceProjectProductInfoList.filter(item=> item.productBomCode=='');
if (mp.length>0){
this.$modal.msgWarning("请完善产品配置信息");
return
}
} }
if (this.form.id != null) { if (this.form.id != null) {

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<!-- 添加或修改订单管理对话框 --> <!-- 添加或修改订单管理对话框 -->
<el-dialog :title="dialogTitle" :visible.sync="internalVisible" width="1400px" append-to-body @close="handleClose"> <el-dialog :close-on-click-modal="false" :title="dialogTitle" :visible.sync="internalVisible" width="1400px" append-to-body @close="handleClose">
<el-form ref="form" :model="form" :rules="rules" label-width="120px" :disabled="isOrderApprovedOrInReview"> <el-form ref="form" :model="form" :rules="rules" label-width="120px" :disabled="isOrderApprovedOrInReview">
<el-tabs v-model="activeTab"> <el-tabs v-model="activeTab">
<el-tab-pane label="基础信息" name="basic"> <el-tab-pane label="基础信息" name="basic">
@ -465,6 +465,11 @@ export default {
this.$modal.msgError("折扣不能大于100%"); this.$modal.msgError("折扣不能大于100%");
return; return;
} }
const checkProduct=(list)=>list.every(item => item.productBomCode!=='')
if (!checkProduct(this.form.softwareProjectProductInfoList) || !checkProduct(this.form.hardwareProjectProductInfoList) || !checkProduct(this.form.maintenanceProjectProductInfoList)) {
this.$modal.msgError("请完善产品信息");
return;
}
this.form.orderStatus = '0'; this.form.orderStatus = '0';
this._performSubmit(); this._performSubmit();
}, },

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<!-- 订单详情抽屉 --> <!-- 订单详情抽屉 -->
<el-drawer :title="title" :visible.sync="internalVisible" direction="rtl" size="70%" @close="handleClose"> <el-drawer :title="title" :wrapper-closable="false" :visible.sync="internalVisible" direction="rtl" size="70%" @close="handleClose">
<div style="padding: 20px;"> <div style="padding: 20px;">
<el-form ref="form" :model="form" :rules="rules" label-width="120px" :disabled="true"> <el-form ref="form" :model="form" :rules="rules" label-width="120px" :disabled="true">
<el-tabs v-model="activeTab"> <el-tabs v-model="activeTab">

View File

@ -329,7 +329,7 @@ export default {
/** 查看审批历史 */ /** 查看审批历史 */
viewApproveLog(row) { viewApproveLog(row) {
// this.$router.push({ path: '/project/order/approveLog/' + row.id }); // this.$router.push({ path: '/project/order/approveLog/' + row.id });
this.msgWarning("查看审批历史功能待实现"); this.$modal.msgWarning("查看审批历史功能待实现");
} }
} }
}; };

View File

@ -90,8 +90,8 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="付款方式" prop="payMethod"> <el-form-item label="付款方式" prop="payType">
<span>{{ selectedVendor.payMethod==='1'?'出库付款':'入库付款' }}</span> <span>{{ selectedVendor.payType===1?'出库付款':'入库付款' }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
@ -419,7 +419,7 @@ export default {
this.selectedVendor = this.vendorOptions.find(item => item.vendorId === vendorId) || {}; this.selectedVendor = this.vendorOptions.find(item => item.vendorId === vendorId) || {};
this.form.warehouseId = this.selectedVendor.warehouseId this.form.warehouseId = this.selectedVendor.warehouseId
this.currentVendorCode=this.selectedVendor.vendorCode; this.currentVendorCode=this.selectedVendor.vendorCode;
this.form.payMethod=this.selectedVendor.payMethod; this.form.payMethod=this.selectedVendor.payType;
} else { } else {
this.selectedVendor = {}; this.selectedVendor = {};
this.form.warehouseId = null; this.form.warehouseId = null;

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog :title="title" :visible.sync="visible" width="80%" append-to-body @close="handleClose"> <el-dialog :title="title" :close-on-click-modal="false" :visible.sync="visible" width="80%" append-to-body @close="handleClose">
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
<el-form-item label="采购单号" prop="purchaseNo"> <el-form-item label="采购单号" prop="purchaseNo">

View File

@ -189,7 +189,7 @@
/> />
<!-- 添加或修改采购单主表对话框 --> <!-- 添加或修改采购单主表对话框 -->
<el-dialog :title="title" :visible.sync="open" width="80vw" append-to-body > <el-dialog :title="title" :close-on-click-modal="false" :visible.sync="open" width="80vw" append-to-body >
<purchase-order-detail ref="purchaseOrderDetail" :order-data="currentOrderData" <purchase-order-detail ref="purchaseOrderDetail" :order-data="currentOrderData"
@close="open = false" @close="open = false"
@success="getList"> @success="getList">
@ -204,6 +204,7 @@
<!-- 流程类型选择对话框 --> <!-- 流程类型选择对话框 -->
<el-dialog <el-dialog
title="选择流程类型" title="选择流程类型"
:close-on-click-modal="false"
:visible.sync="openFlowTypeDialog" :visible.sync="openFlowTypeDialog"
width="30%" width="30%"
append-to-body append-to-body

View File

@ -118,7 +118,7 @@
/> />
<!-- 添加或修改办事处信息对话框 --> <!-- 添加或修改办事处信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body> <el-dialog :title="title" :close-on-click-modal="false" :visible.sync="open" width="800px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="110px"> <el-form ref="form" :model="form" :rules="rules" label-width="110px">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog title="选择代表处" :visible.sync="visible" width="800px" append-to-body @close="handleClose"> <el-dialog title="选择代表处" :visible.sync="visible" :close-on-click-modal="false" width="800px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
<el-form-item label="代表处名称" prop="agentName"> <el-form-item label="代表处名称" prop="agentName">
<el-input <el-input

View File

@ -155,7 +155,7 @@
/> />
<!-- 添加或修改客户信息对话框 --> <!-- 添加或修改客户信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body> <el-dialog :title="title" :visible.sync="open" width="800px" :close-on-click-modal="false" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="120px"> <el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog title="选择客户" :visible.sync="visible" width="800px" append-to-body @close="handleClose"> <el-dialog title="选择客户" :close-on-click-modal="false" :visible.sync="visible" width="800px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
<el-form-item label="客户名称" prop="customerName"> <el-form-item label="客户名称" prop="customerName">
<el-input <el-input

View File

@ -140,7 +140,7 @@
/> />
<!-- 添加或修改代理商管理对话框 --> <!-- 添加或修改代理商管理对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body> <el-dialog :title="title" :visible.sync="open" :close-on-click-modal="false" width="800px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="110px"> <el-form ref="form" :model="form" :rules="rules" label-width="110px">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog title="选择进货商" :visible.sync="visible" width="800px" append-to-body @close="handleClose"> <el-dialog title="选择进货商" :close-on-click-modal="false" :visible.sync="visible" width="800px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
<el-form-item label="进货商名称" prop="partnerName"> <el-form-item label="进货商名称" prop="partnerName">
<el-input <el-input

View File

@ -121,7 +121,7 @@
/> />
<!-- 添加或修改产品管理对话框 --> <!-- 添加或修改产品管理对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body> <el-dialog :title="title" :close-on-click-modal="false" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="110px"> <el-form ref="form" :model="form" :rules="rules" label-width="110px">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog title="选择产品" :visible.sync="visible" width="60%" append-to-body @close="handleClose"> <el-dialog title="选择产品" :close-on-click-modal="false" :visible.sync="visible" width="60%" append-to-body @close="handleClose">
<div style="max-height: 60vh; overflow-y: auto;"> <div style="max-height: 60vh; overflow-y: auto;">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
<el-form-item label="产品编码" prop="productCode"> <el-form-item label="产品编码" prop="productCode">

View File

@ -142,7 +142,7 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination <pagination
v-show="total>0" v-show="total>0"
:total="total" :total="total"
@ -152,7 +152,7 @@
/> />
<!-- 添加或修改仓库基础信息对话框 --> <!-- 添加或修改仓库基础信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body> <el-dialog :title="title" :close-on-click-modal="false" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="110px"> <el-form ref="form" :model="form" :rules="rules" label-width="110px">
<el-form-item label="仓库名称" prop="warehouseName"> <el-form-item label="仓库名称" prop="warehouseName">
<el-input v-model="form.warehouseName" placeholder="请输入仓库名称" /> <el-input v-model="form.warehouseName" placeholder="请输入仓库名称" />

View File

@ -9,7 +9,7 @@ const CompressionPlugin = require('compression-webpack-plugin')
const name = process.env.VUE_APP_TITLE || 'UNISSENSE-OMS' // 网页标题 const name = process.env.VUE_APP_TITLE || 'UNISSENSE-OMS' // 网页标题
const baseUrl = 'http://localhost:28080' // 后端接口 const baseUrl = 'http://localhost:28081' // 后端接口
const port = process.env.port || process.env.npm_config_port || 80 // 端口 const port = process.env.port || process.env.npm_config_port || 80 // 端口

View File

@ -0,0 +1,203 @@
package com.ruoyi.sip.controller;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.config.flow.ProcessConfig;
import com.ruoyi.sip.domain.OmsFinAttachment;
import com.ruoyi.sip.flowable.service.TodoService;
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.OmsInvoiceBill;
import com.ruoyi.sip.service.IOmsInvoiceBillService;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
/**
* Controller
*
* @author ruoyi
* @date 2025-12-22
*/
@RestController
@RequestMapping("/finance/invoice")
public class OmsInvoiceBillController extends BaseController
{
@Autowired
private IOmsInvoiceBillService omsInvoiceBillService;
@Autowired
private IOmsFinAttachmentService omsFinAttachmentService;
@Autowired
private TodoService todoService;
@Autowired
private ProcessConfig processConfig;
/**
*
*/
@RequiresPermissions("sip:invoiceBill:list")
@GetMapping("/list")
public TableDataInfo list(OmsInvoiceBill omsInvoiceBill)
{
startPage();
List<OmsInvoiceBill> list = omsInvoiceBillService.selectOmsInvoiceBillList(omsInvoiceBill);
clearPage();
// todoService.fillApproveNode(list,
// Arrays.asList(processConfig.getDefinition().getFiananceInvoice(), processConfig.getDefinition().getFinanceInvoiceRefound())
// , OmsInvoiceBill::getInvoiceBillCode, (a, b) -> a.setApproveNode(b.get(a.getInvoiceBillCode())));
return getDataTable(list);
}
@PostMapping("/approve/list")
public TableDataInfo listApprove(@RequestBody OmsInvoiceBill omsInvoiceBill) {
startPage();
List<OmsInvoiceBill> list = omsInvoiceBillService.listApprove(omsInvoiceBill);
clearPage();
// todoService.fillApproveNode(list,
// Arrays.asList(omsInvoiceBill.getProcessKey())
// , OmsInvoiceBill::getInvoiceBillCode, (a, b) -> a.setApproveNode(b.get(a.getInvoiceBillCode())));
return getDataTable(list);
}
@PostMapping("/approved/list")
public TableDataInfo listApproved(@RequestBody OmsInvoiceBill omsInvoiceBill) {
startPage();
List<OmsInvoiceBill> list = omsInvoiceBillService.listApproved(omsInvoiceBill);
clearPage();
// todoService.fillApproveNode(list,
// Arrays.asList(processConfig.getDefinition().getFiananceInvoice(), processConfig.getDefinition().getFinanceInvoiceRefound())
// , OmsInvoiceBill::getInvoiceBillCode, (a, b) -> a.setApproveNode(b.get(a.getInvoiceBillCode())));
return getDataTable(list);
}
/**
*
*/
@RequiresPermissions("sip:invoiceBill:export")
@Log(title = "销售开票单", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, OmsInvoiceBill omsInvoiceBill)
{
List<OmsInvoiceBill> list = omsInvoiceBillService.selectOmsInvoiceBillList(omsInvoiceBill);
ExcelUtil<OmsInvoiceBill> util = new ExcelUtil<OmsInvoiceBill>(OmsInvoiceBill.class);
util.exportExcel(response, list, "销售开票单数据");
}
/**
*
*/
@RequiresPermissions("sip:invoiceBill:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return AjaxResult.success(omsInvoiceBillService.selectOmsInvoiceBillById(id));
}
/**
*
*/
@RequiresPermissions("sip:invoiceBill:add")
@Log(title = "销售开票单", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody OmsInvoiceBill omsInvoiceBill)
{
return toAjax(omsInvoiceBillService.insertOmsInvoiceBill(omsInvoiceBill));
}
/**
*
*/
@RequiresPermissions("sip:invoiceBill:edit")
@Log(title = "销售开票单", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody OmsInvoiceBill omsInvoiceBill)
{
return toAjax(omsInvoiceBillService.updateOmsInvoiceBill(omsInvoiceBill));
}
/**
*
*/
@RequiresPermissions("sip:invoiceBill:remove")
@Log(title = "销售开票单", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(omsInvoiceBillService.deleteOmsInvoiceBillByIds(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(OmsInvoiceBill invoiceBill, @RequestParam("file") MultipartFile file)
{
try {
return omsInvoiceBillService.uploadReceipt(invoiceBill, 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 omsInvoiceBillService.applyRefund(id);
} catch (Exception e) {
logger.error("申请红冲失败", e);
return AjaxResult.error("操作失败:" + e.getMessage());
}
}
/**
* 退
*/
@RequiresPermissions("finance:invoice:return")
@Log(title = "退回开票单", businessType = BusinessType.UPDATE)
@DeleteMapping("/return/{id}")
@ResponseBody
public AjaxResult returnInvoice(@PathVariable("id") Long id)
{
try {
// 验证开票单ID
if (id == null) {
return AjaxResult.error("开票ID不能为空");
}
// 调用服务层方法处理退回逻辑
return omsInvoiceBillService.returnInvoice(id);
} catch (Exception e) {
logger.error("退回开票单失败", e);
return AjaxResult.error("操作失败:" + e.getMessage());
}
}
}

View File

@ -1,128 +0,0 @@
package com.ruoyi.sip.controller;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.sip.domain.OmsInvoiceReceiptBill;
import com.ruoyi.sip.service.IOmsInvoiceReceiptBillService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* Controller
*
* @author ruoyi
* @date 2025-10-22
*/
@Controller
@RequestMapping("/finance/invoice")
public class OmsInvoiceReceiptBillController extends BaseController
{
private String prefix = "finance/invoice";
@Autowired
private IOmsInvoiceReceiptBillService omsInvoiceReceiptBillService;
@RequiresPermissions("finance:invoice:view")
@GetMapping()
public String invoice()
{
return prefix + "/invoice";
}
/**
*
*/
@RequiresPermissions("finance:invoice:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(OmsInvoiceReceiptBill omsInvoiceReceiptBill)
{
startPage();
List<OmsInvoiceReceiptBill> list = omsInvoiceReceiptBillService.selectOmsInvoiceReceiptBillList(omsInvoiceReceiptBill);
return getDataTable(list);
}
/**
*
*/
@RequiresPermissions("finance:invoice:export")
@Log(title = "采购收票单", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(OmsInvoiceReceiptBill omsInvoiceReceiptBill)
{
List<OmsInvoiceReceiptBill> list = omsInvoiceReceiptBillService.selectOmsInvoiceReceiptBillList(omsInvoiceReceiptBill);
ExcelUtil<OmsInvoiceReceiptBill> util = new ExcelUtil<OmsInvoiceReceiptBill>(OmsInvoiceReceiptBill.class);
return util.exportExcel(list, "采购收票单数据");
}
/**
*
*/
@RequiresPermissions("finance:invoice:add")
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
*
*/
@RequiresPermissions("finance:invoice:add")
@Log(title = "采购收票单", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(OmsInvoiceReceiptBill omsInvoiceReceiptBill)
{
return toAjax(omsInvoiceReceiptBillService.insertOmsInvoiceReceiptBill(omsInvoiceReceiptBill));
}
/**
*
*/
@RequiresPermissions("finance:invoice:edit")
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id, ModelMap mmap)
{
OmsInvoiceReceiptBill omsInvoiceReceiptBill = omsInvoiceReceiptBillService.selectOmsInvoiceReceiptBillById(id);
mmap.put("omsInvoiceReceiptBill", omsInvoiceReceiptBill);
return prefix + "/edit";
}
/**
*
*/
@RequiresPermissions("finance:invoice:edit")
@Log(title = "采购收票单", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(OmsInvoiceReceiptBill omsInvoiceReceiptBill)
{
return toAjax(omsInvoiceReceiptBillService.updateOmsInvoiceReceiptBill(omsInvoiceReceiptBill));
}
/**
*
*/
@RequiresPermissions("finance:invoice:remove")
@Log(title = "采购收票单", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(omsInvoiceReceiptBillService.deleteOmsInvoiceReceiptBillByIds(ids));
}
}

View File

@ -16,7 +16,6 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.sip.service.IOmsPaymentBillService; import com.ruoyi.sip.service.IOmsPaymentBillService;
import com.ruoyi.sip.service.IOmsInvoiceReceiptBillService;
import com.ruoyi.sip.domain.dto.MergedPaymentDataDto; import com.ruoyi.sip.domain.dto.MergedPaymentDataDto;
import com.ruoyi.sip.domain.dto.MergedReceiptDataDto; import com.ruoyi.sip.domain.dto.MergedReceiptDataDto;
@ -39,8 +38,7 @@ public class OmsPayableBillController extends BaseController
@Autowired @Autowired
private IOmsPaymentBillService omsPaymentBillService; private IOmsPaymentBillService omsPaymentBillService;
@Autowired
private IOmsInvoiceReceiptBillService omsInvoiceReceiptBillService;
@RequiresPermissions("finance:payable:view") @RequiresPermissions("finance:payable:view")
@GetMapping() @GetMapping()

View File

@ -2,10 +2,7 @@ package com.ruoyi.sip.controller;
import java.util.List; import java.util.List;
import com.ruoyi.sip.domain.dto.MergedInvoiceDataDto; import com.ruoyi.sip.domain.dto.*;
import com.ruoyi.sip.domain.dto.MergedPaymentDataDto;
import com.ruoyi.sip.domain.dto.MergedReceiptDataDto;
import com.ruoyi.sip.domain.dto.MergedReceviableReceiptDataDto;
import com.ruoyi.sip.service.IOmsReceivableReceiptDetailService; import com.ruoyi.sip.service.IOmsReceivableReceiptDetailService;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -121,14 +118,14 @@ public class OmsReceivableBillController extends BaseController
/** /**
* *
*/ */
// @RequiresPermissions("inventory:inner:add") // Using permission from button in vue file @RequiresPermissions("inventory:inner:add") // Using permission from button in vue file
// @Log(title = "合并并发起收票单", businessType = BusinessType.INSERT) @Log(title = "合并并发起收票单", businessType = BusinessType.INSERT)
// @PostMapping("/mergeAndInitiateReceipt") @PostMapping("/mergeAndInitiateInvoice")
// @ResponseBody @ResponseBody
// public AjaxResult mergeAndInitiateReceipt(@RequestBody MergedReceiptDataDto dto) public AjaxResult mergeAndInitiateInvoice(@RequestBody MergedReceviableInvoiceDataDto dto)
// { {
// return toAjax(omsPayableBillService.mergeAndInitiateReceipt(dto)); return toAjax(omsReceivableBillService.mergeAndInitiateInvoice(dto));
// } }
} }

View File

@ -71,9 +71,9 @@ public class VueInventoryInfoController extends BaseController {
List<ProductInfo> list = productInfoService.listInventory(info); List<ProductInfo> list = productInfoService.listInventory(info);
return getDataTable(list); return getDataTable(list);
} }
@GetMapping("/list") @PostMapping("/list")
@ResponseBody @ResponseBody
public TableDataInfo list(InventoryInfo inventoryInfo) public TableDataInfo list( InventoryInfo inventoryInfo)
{ {
if (!inventoryAuthService.authAll()) { if (!inventoryAuthService.authAll()) {

View File

@ -59,7 +59,7 @@ public class OmsFinAttachment extends BaseEntity
PAYMENT("payment", "付款单"), PAYMENT("payment", "付款单"),
INVOICE("ticket", "收票单"), INVOICE("ticket", "收票单"),
RECEIPT("receipt", "应收-收款单"), RECEIPT("receipt", "应收-收款单"),
// INVOICE("ticket", "收票单"), RECEIVE_INVOICE("invoice", "应收-收票单"),

View File

@ -0,0 +1,176 @@
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_invoice_bill
*
* @author ruoyi
* @date 2025-12-22
*/
@Data
public class OmsInvoiceBill extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 开票单编号 */
@Excel(name = "开票单编号")
private String invoiceBillCode;
private List<String> invoiceBillCodeList;
/** 票据类型 */
@Excel(name = "票据类型")
private String invoiceType;
/** 开票单类型 (FROM_RECEIVABLE, PRE_INVOICE) */
@Excel(name = "开票单类型 (FROM_RECEIVABLE, PRE_INVOICE)")
private String invoiceBillType;
/** 预计开票时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Excel(name = "预计开票时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date invoiceTime;
/** 客户编码 */
@Excel(name = "客户编码")
private String partnerCode;
private String partnerName;
/** 含税总价 */
@Excel(name = "含税总价")
private BigDecimal totalPriceWithTax;
private BigDecimal invoicePriceWithTax;
/** 未税总价 */
@Excel(name = "未税总价")
private BigDecimal totalPriceWithoutTax;
private BigDecimal invoicePriceWithoutTax;
/** 税率 */
@Excel(name = "税率")
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 actualInvoiceTime;
/** 开票状态 */
@Excel(name = "开票状态")
private String invoiceStatus;
/** 审批状态 */
@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 receivableBillCode;
/** 关联的原始开票单ID */
private Long originalBillId;
private List<PaymentBillPayableDetailDTO> detailList;
private Long approveUser;
private Date applyTime;
private Date todoApproveTime;
private String processKey;
private String todoId;
private String taskId;
public BigDecimal getTaxAmount() {
if (null != totalPriceWithTax && null != totalPriceWithoutTax){
return totalPriceWithTax.subtract(totalPriceWithoutTax);
}
return BigDecimal.ZERO;
}
public BigDecimal getInvoiceAmount() {
if (null != invoicePriceWithTax && null != invoicePriceWithoutTax){
return invoicePriceWithTax.subtract(invoicePriceWithoutTax);
}
return BigDecimal.ZERO;
}
@Getter
public enum InvoiceBillTypeEnum {
/** 应收单生成 */
FROM_RECEIVABLE("FROM_RECEIVABLE", "应收单生成"),
/** 预开票单 */
// PRE_INVOICE("PRE_INVOICE", "预开票单"),
/** 红冲单 */
RED_RUSH("RED_RUSH", "红冲单"),
;
private final String code;
private final String desc;
InvoiceBillTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
}
@Getter
public enum InvoiceStatusEnum {
/** 已红冲 */
RED_RUSH("-1", "已红冲"),
/** 未开票 */
WAIT_INVOICE("1", "未开票"),
/** 已开票 */
INVOICE("2", "已开票"),
;
private final String code;
private final String desc;
InvoiceStatusEnum(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;
}
}
}

View File

@ -1,147 +0,0 @@
package com.ruoyi.sip.domain;
import java.math.BigDecimal;
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_invoice_receipt_bill
*
* @author ruoyi
* @date 2025-10-22
*/
public class OmsInvoiceReceiptBill extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 收票单编号 */
@Excel(name = "收票单编号")
private String invoiceReceiptBillCode;
/** 制造商名称 */
@Excel(name = "制造商名称")
private String vendorCode;
/** 合同编号 */
@Excel(name = "合同编号")
private String orderCode;
/** 含税总价 */
@Excel(name = "含税总价")
private BigDecimal totalPriceWithTax;
/** 未税总价 */
@Excel(name = "未税总价")
private BigDecimal totalPriceWithoutTax;
/** 税额 */
@Excel(name = "税额")
private BigDecimal taxAmount;
/** 删除标志0代表存在 2代表删除 */
private String delFlag;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setInvoiceReceiptBillCode(String invoiceReceiptBillCode)
{
this.invoiceReceiptBillCode = invoiceReceiptBillCode;
}
public String getInvoiceReceiptBillCode()
{
return invoiceReceiptBillCode;
}
public void setVendorCode(String vendorCode)
{
this.vendorCode = vendorCode;
}
public String getVendorCode()
{
return vendorCode;
}
public void setOrderCode(String orderCode)
{
this.orderCode = orderCode;
}
public String getOrderCode()
{
return orderCode;
}
public void setTotalPriceWithTax(BigDecimal totalPriceWithTax)
{
this.totalPriceWithTax = totalPriceWithTax;
}
public BigDecimal getTotalPriceWithTax()
{
return totalPriceWithTax;
}
public void setTotalPriceWithoutTax(BigDecimal totalPriceWithoutTax)
{
this.totalPriceWithoutTax = totalPriceWithoutTax;
}
public BigDecimal getTotalPriceWithoutTax()
{
return totalPriceWithoutTax;
}
public void setTaxAmount(BigDecimal taxAmount)
{
this.taxAmount = taxAmount;
}
public BigDecimal getTaxAmount()
{
return taxAmount;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public String getDelFlag()
{
return delFlag;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("invoiceReceiptBillCode", getInvoiceReceiptBillCode())
.append("vendorCode", getVendorCode())
.append("orderCode", getOrderCode())
.append("totalPriceWithTax", getTotalPriceWithTax())
.append("totalPriceWithoutTax", getTotalPriceWithoutTax())
.append("taxAmount", getTaxAmount())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("delFlag", getDelFlag())
.toString();
}
}

View File

@ -78,7 +78,9 @@ public class OmsReceivableBill extends BaseEntity
@Excel(name = "未收款金额") @Excel(name = "未收款金额")
private BigDecimal unreceivedAmount; private BigDecimal unreceivedAmount;
private BigDecimal planAmount; private BigDecimal planAmount;
private BigDecimal planInvoiceAmount;
private Date planReceiptDate; private Date planReceiptDate;
private Date planInvoiceDate;
/** 已开票金额 */ /** 已开票金额 */
@Excel(name = "已开票金额") @Excel(name = "已开票金额")
@ -90,6 +92,7 @@ public class OmsReceivableBill extends BaseEntity
private String projectName; private String projectName;
private String projectCode; private String projectCode;
private List<OmsReceivableReceiptDetail> detailList; private List<OmsReceivableReceiptDetail> detailList;
private List<OmsReceivableInvoiceDetail> invoiceDetailList;

View File

@ -9,6 +9,7 @@ import lombok.Getter;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.List;
/** /**
* oms_receivable_invoice_detail * oms_receivable_invoice_detail
@ -32,6 +33,7 @@ public class OmsReceivableInvoiceDetail extends BaseEntity
/** 应收单ID */ /** 应收单ID */
@Excel(name = "应收单ID") @Excel(name = "应收单ID")
private Long receivableBillId; private Long receivableBillId;
private List<Long> receivableBillIdList;
/** 实际开票时间 */ /** 实际开票时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ -41,6 +43,8 @@ public class OmsReceivableInvoiceDetail extends BaseEntity
/** 开票金额 */ /** 开票金额 */
@Excel(name = "开票金额") @Excel(name = "开票金额")
private BigDecimal invoiceAmount; private BigDecimal invoiceAmount;
private BigDecimal invoiceAmountWithoutTax;
private BigDecimal invoiceAmountTax;
/** 开票比例 */ /** 开票比例 */
@Excel(name = "开票比例") @Excel(name = "开票比例")
@ -59,6 +63,9 @@ public class OmsReceivableInvoiceDetail extends BaseEntity
private String receivableDetailType; private String receivableDetailType;
private String invoiceStatus; private String invoiceStatus;
private Long invoiceBillId;
private Date actualInvoiceTime;
private OmsFinAttachment attachment;
@Getter @Getter
public enum ReceivableDetailTypeEnum { public enum ReceivableDetailTypeEnum {

View File

@ -0,0 +1,15 @@
package com.ruoyi.sip.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Data
public class MergedReceviableInvoiceDataDto {
private String invoiceBillType;
private Date invoiceTime;
private List<ReceivableOrderInvoiceDto> receivableBills;
private BigDecimal totalMergeInvoiceAmount;
}

View File

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

View File

@ -0,0 +1,91 @@
package com.ruoyi.sip.mapper;
import com.ruoyi.sip.domain.OmsInvoiceBill;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* Mapper
*
* @author ruoyi
* @date 2025-12-22
*/
public interface OmsInvoiceBillMapper
{
/**
*
*
* @param id
* @return
*/
public OmsInvoiceBill selectOmsInvoiceBillById(Long id);
/**
*
*
* @param omsInvoiceBill
* @return
*/
public List<OmsInvoiceBill> selectOmsInvoiceBillList(OmsInvoiceBill omsInvoiceBill);
/**
*
*
* @param omsInvoiceBill
* @return
*/
public int insertOmsInvoiceBill(OmsInvoiceBill omsInvoiceBill);
/**
*
*
* @param omsInvoiceBill
* @return
*/
public int updateOmsInvoiceBill(OmsInvoiceBill omsInvoiceBill);
/**
*
*
* @param id
* @return
*/
public int deleteOmsInvoiceBillById(Long id);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsInvoiceBillByIds(Long[] ids);
/**
*
*
* @param invoiceBillCode
* @return
*/
public OmsInvoiceBill selectOmsInvoiceBillByCode(String invoiceBillCode);
/**
*
*
* @param codePrefix
* @return
*/
public int selectMaxCodeByPrefix(String codePrefix);
/**
*
*
* @param omsInvoiceBill
* @return
*/
public int updateOmsInvoiceBillByCode(OmsInvoiceBill omsInvoiceBill);
List<OmsInvoiceBill> listApprove(@Param("entity") OmsInvoiceBill omsInvoiceBill, @Param("tableName") String tableName);
void clearRelationReceivable(String invoiceBillCode);
}

View File

@ -1,61 +0,0 @@
package com.ruoyi.sip.mapper;
import java.util.List;
import com.ruoyi.sip.domain.OmsInvoiceReceiptBill;
/**
* Mapper
*
* @author ruoyi
* @date 2025-10-22
*/
public interface OmsInvoiceReceiptBillMapper
{
/**
*
*
* @param id
* @return
*/
public OmsInvoiceReceiptBill selectOmsInvoiceReceiptBillById(Long id);
/**
*
*
* @param omsInvoiceReceiptBill
* @return
*/
public List<OmsInvoiceReceiptBill> selectOmsInvoiceReceiptBillList(OmsInvoiceReceiptBill omsInvoiceReceiptBill);
/**
*
*
* @param omsInvoiceReceiptBill
* @return
*/
public int insertOmsInvoiceReceiptBill(OmsInvoiceReceiptBill omsInvoiceReceiptBill);
/**
*
*
* @param omsInvoiceReceiptBill
* @return
*/
public int updateOmsInvoiceReceiptBill(OmsInvoiceReceiptBill omsInvoiceReceiptBill);
/**
*
*
* @param id
* @return
*/
public int deleteOmsInvoiceReceiptBillById(Long id);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsInvoiceReceiptBillByIds(String[] ids);
}

View File

@ -2,7 +2,6 @@ package com.ruoyi.sip.mapper;
import java.util.List; import java.util.List;
import com.ruoyi.sip.domain.OmsPayableTicketDetail;
import com.ruoyi.sip.domain.OmsReceivableInvoiceDetail; import com.ruoyi.sip.domain.OmsReceivableInvoiceDetail;
/** /**
@ -61,7 +60,7 @@ public interface OmsReceivableInvoiceDetailMapper
*/ */
public int deleteOmsReceivableInvoiceDetailByIds(String ids); public int deleteOmsReceivableInvoiceDetailByIds(String ids);
List<OmsReceivableInvoiceDetail> listByReceivableBillIdList(List<Long> collect); List<OmsReceivableInvoiceDetail> list(OmsReceivableInvoiceDetail detail);
/** /**
* ID * ID

View File

@ -0,0 +1,113 @@
package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsInvoiceBill;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.AjaxResult;
/**
* Service
*
* @author ruoyi
* @date 2025-12-22
*/
public interface IOmsInvoiceBillService
{
/**
*
*
* @param id
* @return
*/
public OmsInvoiceBill selectOmsInvoiceBillById(Long id);
/**
*
*
* @param omsInvoiceBill
* @return
*/
public List<OmsInvoiceBill> selectOmsInvoiceBillList(OmsInvoiceBill omsInvoiceBill);
/**
*
*
* @param omsInvoiceBill
* @return
*/
public int insertOmsInvoiceBill(OmsInvoiceBill omsInvoiceBill);
/**
*
*
* @param omsInvoiceBill
* @return
*/
public int updateOmsInvoiceBill(OmsInvoiceBill omsInvoiceBill);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsInvoiceBillByIds(Long[] ids);
/**
*
*
* @param id
* @return
*/
public int deleteOmsInvoiceBillById(Long id);
/**
*
*
* @param bill
* @param file
* @return
*/
public AjaxResult uploadReceipt(OmsInvoiceBill bill, MultipartFile file) throws Exception;
/**
*
*
* @param omsInvoiceBill
* @return
*/
public List<OmsInvoiceBill> listApprove(OmsInvoiceBill omsInvoiceBill);
/**
*
*
* @param omsInvoiceBill
* @return
*/
public List<OmsInvoiceBill> listApproved(OmsInvoiceBill omsInvoiceBill);
/**
*
*
* @param invoiceBillCode
* @return
*/
public OmsInvoiceBill selectOmsInvoiceBillByCode(String invoiceBillCode);
/**
*
*
* @param id ID
* @return
*/
public AjaxResult applyRefund(Long id);
/**
* 退
*
* @param id ID
* @return
*/
public AjaxResult returnInvoice(Long id);
}

View File

@ -1,61 +0,0 @@
package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsInvoiceReceiptBill;
/**
* Service
*
* @author ruoyi
* @date 2025-10-22
*/
public interface IOmsInvoiceReceiptBillService
{
/**
*
*
* @param id
* @return
*/
public OmsInvoiceReceiptBill selectOmsInvoiceReceiptBillById(Long id);
/**
*
*
* @param omsInvoiceReceiptBill
* @return
*/
public List<OmsInvoiceReceiptBill> selectOmsInvoiceReceiptBillList(OmsInvoiceReceiptBill omsInvoiceReceiptBill);
/**
*
*
* @param omsInvoiceReceiptBill
* @return
*/
public int insertOmsInvoiceReceiptBill(OmsInvoiceReceiptBill omsInvoiceReceiptBill);
/**
*
*
* @param omsInvoiceReceiptBill
* @return
*/
public int updateOmsInvoiceReceiptBill(OmsInvoiceReceiptBill omsInvoiceReceiptBill);
/**
*
*
* @param ids
* @return
*/
public int deleteOmsInvoiceReceiptBillByIds(String ids);
/**
*
*
* @param id
* @return
*/
public int deleteOmsInvoiceReceiptBillById(Long id);
}

View File

@ -1,10 +1,11 @@
package com.ruoyi.sip.service; package com.ruoyi.sip.service;
import java.util.List;
import com.ruoyi.sip.domain.OmsReceivableBill; import com.ruoyi.sip.domain.OmsReceivableBill;
import com.ruoyi.sip.domain.dto.MergedInvoiceDataDto; import com.ruoyi.sip.domain.dto.MergedReceviableInvoiceDataDto;
import com.ruoyi.sip.domain.dto.MergedReceviableReceiptDataDto; import com.ruoyi.sip.domain.dto.MergedReceviableReceiptDataDto;
import java.util.List;
/** /**
* Service * Service
* *
@ -73,4 +74,6 @@ public interface IOmsReceivableBillService
public int updateReceiptAmount(List<Long> idList); public int updateReceiptAmount(List<Long> idList);
public int updateInvoiceAmount(List<Long> idList); public int updateInvoiceAmount(List<Long> idList);
int mergeAndInitiateInvoice(MergedReceviableInvoiceDataDto dto);
} }

View File

@ -62,6 +62,7 @@ public interface IOmsReceivableInvoiceDetailService
public int deleteOmsReceivableInvoiceDetailById(Long id); public int deleteOmsReceivableInvoiceDetailById(Long id);
List<OmsReceivableInvoiceDetail> listByReceivableBillIdList(List<Long> collect); List<OmsReceivableInvoiceDetail> listByReceivableBillIdList(List<Long> collect);
List<OmsReceivableInvoiceDetail> listByReceivableBillId(Long receivableBillId);
/** /**
* ID * ID
@ -70,4 +71,6 @@ public interface IOmsReceivableInvoiceDetailService
* @return * @return
*/ */
List<OmsReceivableInvoiceDetail> selectByInvoicePlanIds(List<Long> invoicePlanIds); List<OmsReceivableInvoiceDetail> selectByInvoicePlanIds(List<Long> invoicePlanIds);
List<OmsReceivableInvoiceDetail> listByInvoiceBillCode(String invoiceBillCode);
} }

View File

@ -65,4 +65,6 @@ public interface IOmsReceivableInvoicePlanService
void updateInvoicePlans(Long receivableBillId, List<OmsReceivableInvoicePlan> invoicePlanList); void updateInvoicePlans(Long receivableBillId, List<OmsReceivableInvoicePlan> invoicePlanList);
OmsReceivableInvoicePlan firstUnPayPlan(Long id);
} }

View File

@ -147,6 +147,8 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
inventoryOuterDetail.setId(inventoryDelivery.getDetailId()); inventoryOuterDetail.setId(inventoryDelivery.getDetailId());
inventoryOuterDetail.setWarehouseId(inventoryDelivery.getWarehouseId()); inventoryOuterDetail.setWarehouseId(inventoryDelivery.getWarehouseId());
inventoryOuterDetailMapper.updateInventoryOuterDetail(inventoryOuterDetail); inventoryOuterDetailMapper.updateInventoryOuterDetail(inventoryOuterDetail);
//todo 限制只能发一次货 防止重复发货
int i = inventoryDeliveryMapper.insertInventoryDelivery(inventoryDelivery); int i = inventoryDeliveryMapper.insertInventoryDelivery(inventoryDelivery);
if (CollUtil.isNotEmpty(detailList)){ if (CollUtil.isNotEmpty(detailList)){
for (OmsInventoryDeliveryDetail detail : detailList) { for (OmsInventoryDeliveryDetail detail : detailList) {
@ -318,6 +320,9 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
public List<DeliveryInfoVo> getNumberInfo(ApiDataQueryDto dto) { public List<DeliveryInfoVo> getNumberInfo(ApiDataQueryDto dto) {
List<DeliveryInfoVo> resultList = inventoryDeliveryMapper.listSn(dto); List<DeliveryInfoVo> resultList = inventoryDeliveryMapper.listSn(dto);
List<String> orderCodeList = resultList.stream().map(DeliveryInfoVo::getOrderCode).collect(Collectors.toList()); List<String> orderCodeList = resultList.stream().map(DeliveryInfoVo::getOrderCode).collect(Collectors.toList());
if (CollUtil.isEmpty(orderCodeList)){
return Collections.emptyList();
}
// 根据订单ID查询合同信息 // 根据订单ID查询合同信息
List<ProjectProductInfo> projectProductInfos = projectProductInfoService.selectProjectProductInfoListByOrderCode(orderCodeList); List<ProjectProductInfo> projectProductInfos = projectProductInfoService.selectProjectProductInfoListByOrderCode(orderCodeList);

View File

@ -291,7 +291,7 @@ public class OmsInventoryInnerServiceImpl implements IOmsInventoryInnerService {
throw new ServiceException("产品编码对应产品未找到"); throw new ServiceException("产品编码对应产品未找到");
} }
Map<String, OmsWarehouseInfo> warehouseInfoMap=Collections.emptyMap(); Map<String, OmsWarehouseInfo> warehouseInfoMap=Collections.emptyMap();
if ("2".equalsIgnoreCase(orderType) || (("2".equalsIgnoreCase(productInfos.get(0).getType()) && productInfos.get(0).getVendorName().startsWith("新华三"))) ){ if ("2".equalsIgnoreCase(orderType) || (productInfos.get(0).getVendorName().startsWith("新华三")) ){
List<String> warehouseNameList = inventoryInfoExcelDtoList.stream().map(InventoryInfoExcelDto::getWarehouseName).distinct().collect(Collectors.toList()); List<String> warehouseNameList = inventoryInfoExcelDtoList.stream().map(InventoryInfoExcelDto::getWarehouseName).distinct().collect(Collectors.toList());
if (warehouseNameList.size() > 1){ if (warehouseNameList.size() > 1){
throw new ServiceException("导入清单只能有一个仓库"); throw new ServiceException("导入清单只能有一个仓库");
@ -312,7 +312,7 @@ public class OmsInventoryInnerServiceImpl implements IOmsInventoryInnerService {
info.setModel(productInfos.get(0).getModel()); info.setModel(productInfos.get(0).getModel());
info.setProductDesc(productInfos.get(0).getDescription()); info.setProductDesc(productInfos.get(0).getDescription());
info.setInnerPrice(item.getInnerPrice()); info.setInnerPrice(item.getInnerPrice());
if ("2".equalsIgnoreCase(orderType)|| (("2".equalsIgnoreCase(productInfos.get(0).getType()) && productInfos.get(0).getVendorName().startsWith("新华三"))) ){ if ("2".equalsIgnoreCase(orderType)|| ((productInfos.get(0).getVendorName().startsWith("新华三"))) ){
OmsWarehouseInfo omsWarehouseInfo = finalWarehouseInfoMap.get(item.getWarehouseName()); OmsWarehouseInfo omsWarehouseInfo = finalWarehouseInfoMap.get(item.getWarehouseName());
info.setWarehouseId(omsWarehouseInfo.getId()); info.setWarehouseId(omsWarehouseInfo.getId());
info.setWarehouseName(omsWarehouseInfo.getWarehouseName()); info.setWarehouseName(omsWarehouseInfo.getWarehouseName());

View File

@ -0,0 +1,372 @@
package com.ruoyi.sip.service.impl;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.enums.ApproveStatusEnum;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.sip.domain.OmsReceiptBill;
import com.ruoyi.sip.domain.OmsReceivableInvoiceDetail;
import com.ruoyi.sip.domain.dto.PaymentBillPayableDetailDTO;
import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.service.IOmsFinAttachmentService;
import com.ruoyi.sip.service.IOmsReceivableBillService;
import com.ruoyi.sip.service.IOmsReceivableInvoiceDetailService;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.sip.mapper.OmsInvoiceBillMapper;
import com.ruoyi.sip.domain.OmsInvoiceBill;
import com.ruoyi.sip.service.IOmsInvoiceBillService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.sip.flowable.service.TodoCommonTemplate;
import com.ruoyi.sip.flowable.service.TodoService;
/**
* Service
*
* @author ruoyi
* @date 2025-12-22
*/
@Service
public class OmsInvoiceBillServiceImpl implements IOmsInvoiceBillService, TodoCommonTemplate
{
@Autowired
private OmsInvoiceBillMapper omsInvoiceBillMapper;
@Autowired
private TodoService todoService;
@Autowired
private IOmsFinAttachmentService omsFinAttachmentService;
@Autowired
private IOmsReceivableBillService omsReceivableBillService;
@Autowired
private IOmsReceivableInvoiceDetailService detailService;
/**
*
*
* @param id
* @return
*/
@Override
public OmsInvoiceBill selectOmsInvoiceBillById(Long id)
{
OmsInvoiceBill omsInvoiceBill = omsInvoiceBillMapper.selectOmsInvoiceBillById(id);
// 如果需要关联查询其他数据,可以在这里添加
return omsInvoiceBill;
}
/**
*
*
* @param omsInvoiceBill
* @return
*/
@Override
public List<OmsInvoiceBill> selectOmsInvoiceBillList(OmsInvoiceBill omsInvoiceBill)
{
return omsInvoiceBillMapper.selectOmsInvoiceBillList(omsInvoiceBill);
}
/**
*
*
* @param omsInvoiceBill
* @return
*/
@Override
public int insertOmsInvoiceBill(OmsInvoiceBill omsInvoiceBill)
{
if (StringUtils.isEmpty(omsInvoiceBill.getApproveStatus())){
omsInvoiceBill.setApproveStatus(ApproveStatusEnum.WAIT_COMMIT.getCode());
}
if (StringUtils.isEmpty(omsInvoiceBill.getInvoiceStatus())){
omsInvoiceBill.setInvoiceStatus(OmsInvoiceBill.InvoiceStatusEnum.WAIT_INVOICE.getCode());
}
omsInvoiceBill.setInvoiceBillCode(generateInvoiceBillCode());
omsInvoiceBill.setCreateTime(DateUtils.getNowDate());
return omsInvoiceBillMapper.insertOmsInvoiceBill(omsInvoiceBill);
}
/**
*
*
* @param omsInvoiceBill
* @return
*/
@Override
public int updateOmsInvoiceBill(OmsInvoiceBill omsInvoiceBill)
{
omsInvoiceBill.setUpdateTime(DateUtils.getNowDate());
return omsInvoiceBillMapper.updateOmsInvoiceBill(omsInvoiceBill);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteOmsInvoiceBillByIds(Long[] ids)
{
return omsInvoiceBillMapper.deleteOmsInvoiceBillByIds(ids);
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteOmsInvoiceBillById(Long id)
{
return omsInvoiceBillMapper.deleteOmsInvoiceBillById(id);
}
/**
*
*
* @return
*/
private String generateInvoiceBillCode() {
String prefix = "KP";
// 查询当天已有的最大序列号
String codePrefix = prefix + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_PATTERN);
int maxSequence = omsInvoiceBillMapper.selectMaxCodeByPrefix(codePrefix);
// 生成新的序列号
int newSequence = maxSequence + 1;
// 序列号补零到4位
String sequenceStr = String.format("%04d", newSequence);
return codePrefix + sequenceStr;
}
/**
*
*
* @param bill
* @param file
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public AjaxResult uploadReceipt(OmsInvoiceBill bill, MultipartFile file) throws Exception {
OmsInvoiceBill omsInvoiceBill = selectOmsInvoiceBillById(bill.getId());
if (omsInvoiceBill == null) {
throw new ServiceException("开票单不存在");
}
// 检查开票金额是否与应收单一致
if (omsInvoiceBill.getTotalPriceWithTax().compareTo(bill.getInvoicePriceWithTax()) != 0){
return AjaxResult.error("开票金额与应收单金额不一致");
}
// 这里可以添加上传附件的逻辑
// omsFinAttachmentService.uploadAttachment(file, omsInvoiceBill.getId(), "INVOICE_RECEIPT");
omsInvoiceBill.setActualInvoiceTime(DateUtils.getNowDate());
omsInvoiceBill.setApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode());
omsInvoiceBill.setInvoicePriceWithTax(bill.getInvoicePriceWithTax());
omsInvoiceBill.setInvoicePriceWithoutTax(bill.getInvoicePriceWithoutTax());
omsInvoiceBill.setInvoiceType(bill.getInvoiceType());
updateOmsInvoiceBill(omsInvoiceBill);
// // 根据开票单类型启动不同流程
// if (OmsInvoiceBill.InvoiceBillTypeEnum.FROM_RECEIVABLE.getCode().equals(omsInvoiceBill.getInvoiceBillType())) {
// todoService.startProcessDeleteBefore(omsInvoiceBill.getInvoiceBillCode(), omsInvoiceBill.getInvoiceBillCode(),
// "financeInvoice", omsInvoiceBill.getCreateBy());
// } else {
// todoService.startProcessDeleteBefore(omsInvoiceBill.getInvoiceBillCode(), omsInvoiceBill.getInvoiceBillCode(),
// "financeInvoiceRefound", omsInvoiceBill.getCreateBy());
// }
return AjaxResult.success("上传成功");
}
/**
*
*
* @param omsInvoiceBill
* @return
*/
@Override
public List<OmsInvoiceBill> listApprove(OmsInvoiceBill omsInvoiceBill) {
omsInvoiceBill.setApproveUser(ShiroUtils.getUserId());
return omsInvoiceBillMapper.listApprove(omsInvoiceBill, "bu_todo");
}
/**
*
*
* @param omsInvoiceBill
* @return
*/
@Override
public List<OmsInvoiceBill> listApproved(OmsInvoiceBill omsInvoiceBill) {
omsInvoiceBill.setApproveUser(ShiroUtils.getUserId());
return omsInvoiceBillMapper.listApprove(omsInvoiceBill, "bu_todo_completed");
}
/**
*
*
* @param invoiceBillCode
* @return
*/
@Override
public OmsInvoiceBill selectOmsInvoiceBillByCode(String invoiceBillCode) {
return omsInvoiceBillMapper.selectOmsInvoiceBillByCode(invoiceBillCode);
}
/**
*
*
* @param id ID
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public AjaxResult applyRefund(Long id) {
OmsInvoiceBill originalBill = selectOmsInvoiceBillById(id);
if (originalBill == null) {
return AjaxResult.error("开票单不存在");
}
// 检查是否已红冲
if (!OmsInvoiceBill.InvoiceStatusEnum.INVOICE.getCode().equals(originalBill.getInvoiceStatus())) {
return AjaxResult.error("只有已开票状态的单据才能申请红冲");
}
// 检查是否已经申请过红冲
if (OmsInvoiceBill.RefundStatusEnum.REFUNDED.getCode().equals(originalBill.getRefundStatus())) {
return AjaxResult.error("该单据已申请红冲,不能重复申请");
}
// 创建红冲单
OmsInvoiceBill refundBill = new OmsInvoiceBill();
refundBill.setInvoiceBillCode(generateInvoiceBillCode());
refundBill.setInvoiceType(originalBill.getInvoiceType());
refundBill.setPartnerCode(originalBill.getPartnerCode());
refundBill.setTotalPriceWithTax(originalBill.getTotalPriceWithTax().negate()); // 负数金额
refundBill.setTotalPriceWithoutTax(originalBill.getTotalPriceWithoutTax().negate());
refundBill.setTaxRate(originalBill.getTaxRate());
refundBill.setApproveStatus(ApproveStatusEnum.WAIT_COMMIT.getCode());
refundBill.setInvoiceBillType(OmsInvoiceBill.InvoiceBillTypeEnum.RED_RUSH.getCode());
refundBill.setInvoiceStatus(OmsInvoiceBill.InvoiceStatusEnum.INVOICE.getCode());
refundBill.setRefundStatus(OmsInvoiceBill.RefundStatusEnum.REFUNDED.getCode());
refundBill.setOriginalBillId(originalBill.getId()); // 关联原始单据
refundBill.setCreateTime(DateUtils.getNowDate());
insertOmsInvoiceBill(refundBill);
// 更新原单据的红冲状态
originalBill.setRefundStatus(OmsInvoiceBill.RefundStatusEnum.REFUNDED.getCode());
updateOmsInvoiceBill(originalBill);
return AjaxResult.success("红冲申请已提交");
}
/**
* 退
*
* @param id ID
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public AjaxResult returnInvoice(Long id) {
OmsInvoiceBill invoiceBill = selectOmsInvoiceBillById(id);
if (invoiceBill == null){
return AjaxResult.error("开票单不存在");
}
// 2. 检查开票单类型只有FROM_RECEIVABLE类型的开票单才能退回
if (!OmsInvoiceBill.InvoiceBillTypeEnum.FROM_RECEIVABLE.getCode().equals(invoiceBill.getInvoiceBillType())) {
return AjaxResult.error("只有由应收单合并生成的开票单才能执行退回操作");
}
List<OmsReceivableInvoiceDetail> omsReceivableInvoiceDetails = detailService.listByInvoiceBillCode(invoiceBill.getInvoiceBillCode());
omsInvoiceBillMapper.clearRelationReceivable(invoiceBill.getInvoiceBillCode());
int result = omsInvoiceBillMapper.deleteOmsInvoiceBillById(id);
if (result <= 0) {
throw new RuntimeException("删除开票单失败");
}
if (CollUtil.isNotEmpty(omsReceivableInvoiceDetails)){
omsReceivableBillService.updateInvoiceAmount(omsReceivableInvoiceDetails.stream()
.map(OmsReceivableInvoiceDetail::getReceivableBillId).distinct().collect(Collectors.toList()));
}
return AjaxResult.success("退回开票单成功");
}
@Override
public Object todoDetail(String businessKey, String processKey, String todoId) {
return null;
}
@Override
public Object completedTodoDetail(String businessKey, String processKey, String todoId) {
return null;
}
@Override
public void fillBusinessInfo(List<Todo> todoCompletedList) {
}
@Override
public boolean todoApproveCallback(Todo todo) {
return TodoCommonTemplate.super.todoApproveCallback(todo);
}
@Override
public boolean multiInstanceApproveCallback(String activityName, ProcessInstance processInstance) {
return TodoCommonTemplate.super.multiInstanceApproveCallback(activityName, processInstance);
}
// @Override
// public String getBusinessKey() {
// return "invoiceBillCode";
// }
//
// @Override
// public void reject(String businessKey) {
// OmsInvoiceBill omsInvoiceBill = new OmsInvoiceBill();
// omsInvoiceBill.setInvoiceBillCode(businessKey);
// omsInvoiceBill.setApproveStatus(ApproveStatusEnum.APPROVE_REJECT.getCode());
// omsInvoiceBillMapper.updateOmsInvoiceBillByCode(omsInvoiceBill);
// }
//
// @Override
// public void approve(String businessKey) {
// OmsInvoiceBill omsInvoiceBill = new OmsInvoiceBill();
// omsInvoiceBill.setInvoiceBillCode(businessKey);
// omsInvoiceBill.setApproveStatus(ApproveStatusEnum.APPROVE_COMPLETE.getCode());
// omsInvoiceBill.setInvoiceStatus(OmsInvoiceBill.InvoiceStatusEnum.INVOICE.getCode());
// omsInvoiceBill.setApproveTime(DateUtils.getNowDate());
// omsInvoiceBillMapper.updateOmsInvoiceBillByCode(omsInvoiceBill);
//
// OmsInvoiceBill existBill = selectOmsInvoiceBillByCode(businessKey);
// // 如果需要更新关联的应收单状态,可以在这里添加逻辑
// // omsReceivableBillService.updateInvoiceAmount(existBill.getReceivableBillCode(), existBill.getTotalPriceWithTax());
// }
}

View File

@ -1,97 +0,0 @@
package com.ruoyi.sip.service.impl;
import java.util.List;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.sip.mapper.OmsInvoiceReceiptBillMapper;
import com.ruoyi.sip.domain.OmsInvoiceReceiptBill;
import com.ruoyi.sip.service.IOmsInvoiceReceiptBillService;
import com.ruoyi.common.core.text.Convert;
/**
* Service
*
* @author ruoyi
* @date 2025-10-22
*/
@Service
public class OmsInvoiceReceiptBillServiceImpl implements IOmsInvoiceReceiptBillService
{
@Autowired
private OmsInvoiceReceiptBillMapper omsInvoiceReceiptBillMapper;
/**
*
*
* @param id
* @return
*/
@Override
public OmsInvoiceReceiptBill selectOmsInvoiceReceiptBillById(Long id)
{
return omsInvoiceReceiptBillMapper.selectOmsInvoiceReceiptBillById(id);
}
/**
*
*
* @param omsInvoiceReceiptBill
* @return
*/
@Override
public List<OmsInvoiceReceiptBill> selectOmsInvoiceReceiptBillList(OmsInvoiceReceiptBill omsInvoiceReceiptBill)
{
return omsInvoiceReceiptBillMapper.selectOmsInvoiceReceiptBillList(omsInvoiceReceiptBill);
}
/**
*
*
* @param omsInvoiceReceiptBill
* @return
*/
@Override
public int insertOmsInvoiceReceiptBill(OmsInvoiceReceiptBill omsInvoiceReceiptBill)
{
omsInvoiceReceiptBill.setCreateTime(DateUtils.getNowDate());
return omsInvoiceReceiptBillMapper.insertOmsInvoiceReceiptBill(omsInvoiceReceiptBill);
}
/**
*
*
* @param omsInvoiceReceiptBill
* @return
*/
@Override
public int updateOmsInvoiceReceiptBill(OmsInvoiceReceiptBill omsInvoiceReceiptBill)
{
omsInvoiceReceiptBill.setUpdateTime(DateUtils.getNowDate());
return omsInvoiceReceiptBillMapper.updateOmsInvoiceReceiptBill(omsInvoiceReceiptBill);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteOmsInvoiceReceiptBillByIds(String ids)
{
return omsInvoiceReceiptBillMapper.deleteOmsInvoiceReceiptBillByIds(Convert.toStrArray(ids));
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteOmsInvoiceReceiptBillById(Long id)
{
return omsInvoiceReceiptBillMapper.deleteOmsInvoiceReceiptBillById(id);
}
}

View File

@ -16,8 +16,7 @@ import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.sip.domain.*; import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.domain.dto.MergedReceviableReceiptDataDto; import com.ruoyi.sip.domain.dto.*;
import com.ruoyi.sip.domain.dto.ReceivableOrderReceiptDto;
import com.ruoyi.sip.service.*; import com.ruoyi.sip.service.*;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -40,6 +39,9 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
@Autowired @Autowired
private IOmsReceiptBillService receiptBillService; private IOmsReceiptBillService receiptBillService;
@Autowired
private IOmsInvoiceBillService invoiceBillService;
@Autowired @Autowired
private IOmsReceivableReceiptDetailService detailService; private IOmsReceivableReceiptDetailService detailService;
@ -83,7 +85,7 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
Map<String, BigDecimal> decimalMap = receiptBills.stream().filter(item -> item.getRemainingAmount() != null) Map<String, BigDecimal> decimalMap = receiptBills.stream().filter(item -> item.getRemainingAmount() != null)
.collect(Collectors.toMap(OmsReceiptBill::getPartnerCode, OmsReceiptBill::getRemainingAmount, BigDecimal::add)); .collect(Collectors.toMap(OmsReceiptBill::getPartnerCode, OmsReceiptBill::getRemainingAmount, BigDecimal::add));
for (OmsReceivableBill payableBill : receivableBills) { for (OmsReceivableBill payableBill : receivableBills) {
payableBill.setReceivedAmount(decimalMap.getOrDefault(payableBill.getPartnerCode(), BigDecimal.ZERO)); payableBill.setRemainingAmount(decimalMap.getOrDefault(payableBill.getPartnerCode(), BigDecimal.ZERO));
} }
} }
return receivableBills; return receivableBills;
@ -139,6 +141,8 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
OmsReceivableBill omsReceivableBill = omsReceivableBillMapper.selectOmsReceivableBillById(id); OmsReceivableBill omsReceivableBill = omsReceivableBillMapper.selectOmsReceivableBillById(id);
List<OmsReceivableReceiptDetail> detailList = detailService.listByReceivableBillId(id); List<OmsReceivableReceiptDetail> detailList = detailService.listByReceivableBillId(id);
omsReceivableBill.setDetailList(detailList); omsReceivableBill.setDetailList(detailList);
List<OmsReceivableInvoiceDetail> omsReceivableInvoiceDetails = invoiceDetailService.listByReceivableBillId(id);
omsReceivableBill.setInvoiceDetailList(omsReceivableInvoiceDetails);
return omsReceivableBill; return omsReceivableBill;
} }
@ -259,39 +263,146 @@ public class OmsReceivableBillServiceImpl implements IOmsReceivableBillService
} }
List<OmsReceivableInvoiceDetail> invoiceDetails = invoiceDetailService.listByReceivableBillIdList(idList); List<OmsReceivableInvoiceDetail> invoiceDetails = invoiceDetailService.listByReceivableBillIdList(idList);
java.util.Map<Long, java.util.Map<String, BigDecimal>> planMap = invoiceDetails.stream() Map<Long, Map<Long, OmsReceivableInvoiceDetail>> planMap = invoiceDetails.stream().collect(Collectors.groupingBy(
.collect(java.util.stream.Collectors.groupingBy( OmsReceivableInvoiceDetail::getReceivableBillId,
OmsReceivableInvoiceDetail::getReceivableBillId, Collectors.toMap(
java.util.stream.Collectors.groupingBy( OmsReceivableInvoiceDetail::getInvoicePlanId,
item -> item.getReceivableDetailType() == null ? OmsReceivableInvoiceDetail.ReceivableDetailTypeEnum.NORMAL_INVOICE.getCode() : item.getReceivableDetailType(), Function.identity(),
java.util.stream.Collectors.reducing( (d1, d2) -> d1.getCreateTime().after(d2.getCreateTime()) ? d1 : d2
BigDecimal.ZERO, )
detail -> (detail.getInvoiceAmount() != null) ? detail.getInvoiceAmount() : BigDecimal.ZERO, ));
BigDecimal::add
))));
for (OmsReceivableBill bill : bills) { for (OmsReceivableBill bill : bills) {
java.util.Map<String, BigDecimal> amountMap = planMap.get(bill.getId()); Map<Long, OmsReceivableInvoiceDetail> paymentDetailMap =
if (CollUtil.isNotEmpty(amountMap)) { planMap.getOrDefault(bill.getId(), Collections.emptyMap());
// 已开票金额 = 正常开票金额 - 红冲金额 if (CollUtil.isNotEmpty(paymentDetailMap)) {
BigDecimal invoicedAmount = amountMap.getOrDefault(OmsReceivableInvoiceDetail.ReceivableDetailTypeEnum.NORMAL_INVOICE.getCode(), BigDecimal.ZERO) Map<String, BigDecimal> amountMap =
.subtract(amountMap.getOrDefault(OmsReceivableInvoiceDetail.ReceivableDetailTypeEnum.REFUND.getCode(), BigDecimal.ZERO)); paymentDetailMap.values().stream()
bill.setInvoicedAmount(invoicedAmount); .filter(d -> d.getInvoiceAmount() != null)
// 未开票金额 = 总金额 - 已开票金额 .collect(Collectors.toMap(
bill.setUninvoicedAmount(bill.getTotalPriceWithTax().subtract(invoicedAmount)); OmsReceivableInvoiceDetail::getInvoiceStatus,
OmsReceivableInvoiceDetail::getInvoiceAmount,
BigDecimal::add
));
// 4. 金额计算(集中处理,逻辑更清晰)
BigDecimal paidAmount = amountMap
.getOrDefault(OmsInvoiceBill.InvoiceStatusEnum.INVOICE.getCode(), BigDecimal.ZERO)
.add(amountMap.getOrDefault(
OmsInvoiceBill.InvoiceStatusEnum.RED_RUSH.getCode(), BigDecimal.ZERO));
BigDecimal waitPayAmount =
amountMap.getOrDefault(
OmsInvoiceBill.InvoiceStatusEnum.WAIT_INVOICE.getCode(), BigDecimal.ZERO);
bill.setInvoicedAmount(paidAmount);
bill.setUninvoicedAmount(bill.getTotalPriceWithTax().subtract(paidAmount)
.subtract(waitPayAmount));
} }
// 获取最新未开票计划 OmsReceivableInvoicePlan lastReceiptPlan = invoicePlanService.firstUnPayPlan(bill.getId());
OmsReceivableInvoicePlan lastInvoicePlan = invoicePlanService.selectOmsReceivableInvoicePlanList(new OmsReceivableInvoicePlan() {{ bill.setLastReceiptPlanId(lastReceiptPlan == null ? -1 : lastReceiptPlan.getId());
setReceivableBillId(bill.getId());
}}).stream()
.filter(p -> p.getDetailId() == null) // 查找未执行的开票计划
.min(java.util.Comparator.comparing(OmsReceivableInvoicePlan::getPlanInvoiceDate))
.orElse(null);
bill.setLastInvoicePlanId(lastInvoicePlan == null ? -1L : lastInvoicePlan.getId());
} }
return omsReceivableBillMapper.updateBatchReceivableBillInvoiceInfo(bills); return omsReceivableBillMapper.updateBatchReceivableBillInvoiceInfo(bills);
} }
@Override
public int mergeAndInitiateInvoice(MergedReceviableInvoiceDataDto dto) {
// 1. Calculate Tax Totals
BigDecimal totalWithoutTax = BigDecimal.ZERO;
if (CollUtil.isEmpty(dto.getReceivableBills())) {
return 0;
}
// Fetch bills once
for (ReceivableOrderInvoiceDto order : dto.getReceivableBills()) {
BigDecimal taxRate = order.getTaxRate();
if (taxRate == null || taxRate.compareTo(BigDecimal.ZERO) < 0) {
// 如果税率为空或小于0则默认为0
taxRate = new BigDecimal(defaultTax);
}
order.setTaxRate(taxRate);
for (OmsReceivableInvoicePlan plan : order.getInvoicePlans()) {
// 计算每个 plan 的未税金额 = planAmount / (1 + 税率),保留两位小数
// 计算未税金额 = planAmount / (1 + 税率)
BigDecimal divisor = BigDecimal.ONE.add(taxRate);
BigDecimal planWithoutTax = plan.getPlanAmount().divide(divisor, 2, java.math.RoundingMode.HALF_UP);
totalWithoutTax = totalWithoutTax.add(planWithoutTax);
}
}
// 2. 创建收票单
OmsInvoiceBill invoiceBill = new OmsInvoiceBill();
OmsReceivableBill firstReceivableBill = selectOmsReceivableBillById(dto.getReceivableBills().get(0).getId());
invoiceBill.setInvoiceBillType(dto.getInvoiceBillType());
invoiceBill.setInvoiceTime(dto.getInvoiceTime());
invoiceBill.setPartnerCode(firstReceivableBill.getPartnerCode());
invoiceBill.setPartnerName(firstReceivableBill.getPartnerName());
invoiceBill.setTotalPriceWithTax(dto.getTotalMergeInvoiceAmount());
// Set Calculated Tax Info
invoiceBill.setTotalPriceWithoutTax(totalWithoutTax);
invoiceBill.setInvoiceBillType(OmsInvoiceBill.InvoiceBillTypeEnum.FROM_RECEIVABLE.getCode());
invoiceBill.setInvoiceStatus(OmsInvoiceBill.InvoiceStatusEnum.WAIT_INVOICE.getCode());
invoiceBillService.insertOmsInvoiceBill(invoiceBill);
// 3. 创建收票明细 - 防止重复收票
// 收集所有收票计划ID
List<Long> allInvoicePlanIds = dto.getReceivableBills().stream()
.flatMap(order -> order.getInvoicePlans().stream())
.map(OmsReceivableInvoicePlan::getId)
.collect(Collectors.toList());
// 查询现有的收票明细记录
Map<Long, OmsReceivableInvoiceDetail> existingDetailsMap = new java.util.HashMap<>();
if (!allInvoicePlanIds.isEmpty()) {
List<OmsReceivableInvoiceDetail> omsReceivableInvoiceDetails = invoiceDetailService.selectByInvoicePlanIds(allInvoicePlanIds);
// 使用stream将查询结果转化为Map以planId为keydetail为value取createtime最新的数据
existingDetailsMap = omsReceivableInvoiceDetails.stream()
.collect(Collectors.toMap(
OmsReceivableInvoiceDetail::getInvoicePlanId,
detail -> detail,
// 如果有重复数据取createtime最新的数据
(existing, replacement) -> existing.getCreateTime().compareTo(replacement.getCreateTime()) >= 0 ? existing : replacement
));
}
// 遍历所有计划并检查是否有已收票的记录
for (ReceivableOrderInvoiceDto invoiceDto : dto.getReceivableBills()) {
for (OmsReceivableInvoicePlan invoicePlan : invoiceDto.getInvoicePlans()) {
// 检查是否存在已收票的记录
OmsReceivableInvoiceDetail existingDetail = existingDetailsMap.get(invoicePlan.getId());
if (existingDetail != null) {
// 检查是否是已收票状态,如果是则抛出异常
if (!OmsPayableTicketDetail.PayableDetailTypeEnum.RED_RUSH.getCode().equals(existingDetail.getReceivableDetailType())) {
throw new ServiceException("计划ID为 " + invoicePlan.getId() + " 的收票已处理,请刷新页面后重试");
}
}
OmsReceivableInvoiceDetail detail = new OmsReceivableInvoiceDetail();
detail.setReceivableBillId(invoiceDto.getId());
detail.setInvoicePlanId(invoicePlan.getId());
detail.setInvoiceBillCode(invoiceBill.getInvoiceBillCode());
detail.setInvoiceAmount(invoicePlan.getPlanAmount());
detail.setInvoiceRate(invoicePlan.getPlanRate());
detail.setInvoiceAmountWithoutTax(detail.getInvoiceAmount().divide(BigDecimal.ONE.add(invoiceDto.getTaxRate()), 2, java.math.RoundingMode.HALF_UP));
detail.setInvoiceAmountTax(detail.getInvoiceAmount().subtract(detail.getInvoiceAmountWithoutTax()));
detail.setInvoiceTime(invoicePlan.getPlanInvoiceDate());
detail.setRemark(invoicePlan.getRemark());
detail.setCreateBy(ShiroUtils.getUserId().toString());
detail.setReceivableDetailType(OmsReceivableInvoiceDetail.ReceivableDetailTypeEnum.NORMAL_INVOICE.getCode());
invoiceDetailService.insertOmsReceivableInvoiceDetail(detail);
}
}
// 批量更新应付单的收票相关信息
return SpringUtils.getAopProxy(this).updateInvoiceAmount(dto.getReceivableBills().stream()
.map(ReceivableOrderInvoiceDto::getId).collect(Collectors.toList()));
}
@Override @Override
public int updateReceiptAmount(List<Long> idList) { public int updateReceiptAmount(List<Long> idList) {
if (CollUtil.isEmpty(idList)) { if (CollUtil.isEmpty(idList)) {

View File

@ -2,8 +2,13 @@ package com.ruoyi.sip.service.impl;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.ruoyi.sip.domain.OmsPayableTicketDetail; import cn.hutool.core.collection.CollUtil;
import com.ruoyi.sip.domain.OmsFinAttachment;
import com.ruoyi.sip.service.IOmsFinAttachmentService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.ruoyi.sip.mapper.OmsReceivableInvoiceDetailMapper; import com.ruoyi.sip.mapper.OmsReceivableInvoiceDetailMapper;
@ -22,6 +27,8 @@ public class OmsReceivableInvoiceDetailServiceImpl implements IOmsReceivableInvo
@Autowired @Autowired
private OmsReceivableInvoiceDetailMapper omsReceivableInvoiceDetailMapper; private OmsReceivableInvoiceDetailMapper omsReceivableInvoiceDetailMapper;
@Autowired
private IOmsFinAttachmentService finAttachmentService;
/** /**
* *
* *
@ -96,7 +103,33 @@ public class OmsReceivableInvoiceDetailServiceImpl implements IOmsReceivableInvo
@Override @Override
public List<OmsReceivableInvoiceDetail> listByReceivableBillIdList(List<Long> collect) { public List<OmsReceivableInvoiceDetail> listByReceivableBillIdList(List<Long> collect) {
return omsReceivableInvoiceDetailMapper.listByReceivableBillIdList(collect);
if (CollUtil.isEmpty(collect)){
return Collections.emptyList();
}
OmsReceivableInvoiceDetail omsReceivableInvoiceDetail = new OmsReceivableInvoiceDetail();
omsReceivableInvoiceDetail.setReceivableBillIdList(collect);
return omsReceivableInvoiceDetailMapper.list(omsReceivableInvoiceDetail);
}
@Override
public List<OmsReceivableInvoiceDetail> listByReceivableBillId(Long receivableBillId) {
OmsReceivableInvoiceDetail omsReceivableInvoiceDetail = new OmsReceivableInvoiceDetail();
omsReceivableInvoiceDetail.setReceivableBillId(receivableBillId);
List<OmsReceivableInvoiceDetail> list = omsReceivableInvoiceDetailMapper.list(omsReceivableInvoiceDetail);
if (CollUtil.isNotEmpty(list)){
OmsFinAttachment omsFinAttachment = new OmsFinAttachment();
omsFinAttachment.setRelatedBillIdList(list.stream().map(OmsReceivableInvoiceDetail::getInvoiceBillId).distinct().collect(Collectors.toList()));
omsFinAttachment.setRelatedBillType(OmsFinAttachment.RelatedBillTypeEnum.RECEIVE_INVOICE.getCode());
omsFinAttachment.setDelFlag("0");
List<OmsFinAttachment> attachmentList = finAttachmentService.selectOmsFinAttachmentList(omsFinAttachment);
Map<Long, OmsFinAttachment> collect = attachmentList.stream().collect(Collectors.toMap(OmsFinAttachment::getRelatedBillId, Function.identity()));
for (OmsReceivableInvoiceDetail detail : list) {
detail.setAttachment(collect.get(detail.getInvoiceBillId()));
}
}
return list;
} }
@Override @Override
@ -106,4 +139,11 @@ public class OmsReceivableInvoiceDetailServiceImpl implements IOmsReceivableInvo
} }
return omsReceivableInvoiceDetailMapper.selectByInvoicePlanIds(invoicePlanIds); return omsReceivableInvoiceDetailMapper.selectByInvoicePlanIds(invoicePlanIds);
} }
@Override
public List<OmsReceivableInvoiceDetail> listByInvoiceBillCode(String invoiceBillCode) {
OmsReceivableInvoiceDetail omsReceivableInvoiceDetail = new OmsReceivableInvoiceDetail();
omsReceivableInvoiceDetail.setInvoiceBillCode(invoiceBillCode);
return omsReceivableInvoiceDetailMapper.list(omsReceivableInvoiceDetail);
}
} }

View File

@ -110,19 +110,19 @@ public class OmsReceivableInvoicePlanServiceImpl implements IOmsReceivableInvoic
OmsReceivableInvoicePlan omsReceivableInvoicePlan = new OmsReceivableInvoicePlan(); OmsReceivableInvoicePlan omsReceivableInvoicePlan = new OmsReceivableInvoicePlan();
omsReceivableInvoicePlan.setReceivableBillId(receivableBillId); omsReceivableInvoicePlan.setReceivableBillId(receivableBillId);
List<OmsReceivableInvoicePlan> omsReceivableInvoicePlans = omsReceivableInvoicePlanMapper.selectOmsReceivableInvoicePlanList(omsReceivableInvoicePlan); List<OmsReceivableInvoicePlan> omsReceivableInvoicePlans = omsReceivableInvoicePlanMapper.selectOmsReceivableInvoicePlanList(omsReceivableInvoicePlan);
// if (CollUtil.isNotEmpty(omsReceivableInvoicePlans)) { if (CollUtil.isNotEmpty(omsReceivableInvoicePlans)) {
// List<OmsReceivableInvoiceDetail> omsPayablePaymentDetails = detailService.listByReceivableBillIdList(omsReceivableInvoicePlans.stream().map(OmsReceivableInvoicePlan::getReceivableBillId).collect(Collectors.toList())); List<OmsReceivableInvoiceDetail> omsPayablePaymentDetails = detailService.listByReceivableBillIdList(omsReceivableInvoicePlans.stream().map(OmsReceivableInvoicePlan::getReceivableBillId).collect(Collectors.toList()));
// Map<Long, OmsReceivableInvoiceDetail> detailMap = omsPayablePaymentDetails.stream().collect(Collectors.toMap(OmsReceivableInvoiceDetail::getInvoicePlanId, Function.identity(), Map<Long, OmsReceivableInvoiceDetail> detailMap = omsPayablePaymentDetails.stream().collect(Collectors.toMap(OmsReceivableInvoiceDetail::getInvoicePlanId, Function.identity(),
// (v1, v2) -> v1.getCreateTime().after(v2.getCreateTime()) ? v1 : v2)); (v1, v2) -> v1.getCreateTime().after(v2.getCreateTime()) ? v1 : v2));
// for (OmsReceivableInvoicePlan plan : omsReceivableInvoicePlans) { for (OmsReceivableInvoicePlan plan : omsReceivableInvoicePlans) {
// //找到最新的一条数据 如果不是退款 那么不允许再次勾选 //找到最新的一条数据 如果不是退款 那么不允许再次勾选
// OmsReceivableInvoiceDetail detail = detailMap.get(plan.getId()); OmsReceivableInvoiceDetail detail = detailMap.get(plan.getId());
// if (detail != null && !OmsReceivableInvoiceDetail.PayableDetailTypeEnum.RED_RUSH.getCode().equalsIgnoreCase(detail.getInvoiceDetailType())) { if (detail != null && !OmsReceivableInvoiceDetail.ReceivableDetailTypeEnum.REFUND.getCode().equalsIgnoreCase(detail.getReceivableDetailType())) {
//
// plan.setDetailId(detail.getId()); plan.setDetailId(detail.getId());
// } }
// } }
// } }
return omsReceivableInvoicePlans; return omsReceivableInvoicePlans;
} }
@ -164,4 +164,9 @@ public class OmsReceivableInvoicePlanServiceImpl implements IOmsReceivableInvoic
billMapper.updateOmsReceivableBill(receivableBill); billMapper.updateOmsReceivableBill(receivableBill);
} }
@Override
public OmsReceivableInvoicePlan firstUnPayPlan(Long id) {
return omsReceivableInvoicePlanMapper.firstUnPayPlan(id);
}
} }

View File

@ -207,7 +207,7 @@ public class OmsReceivableReceiptPlanServiceImpl implements IOmsReceivableReceip
if (!hasExecutedInvoice) { if (!hasExecutedInvoice) {
List<OmsReceivableInvoicePlan> newPlans = convertReceiptToInvoice(receiptPlans, receivableBillId); List<OmsReceivableInvoicePlan> newPlans = convertReceiptToInvoice(receiptPlans, receivableBillId);
updateInvoicePlan(receivableBillId, newPlans); invoicePlanService.updateInvoicePlans(receivableBillId, newPlans);
} else { } else {
List<OmsReceivableInvoicePlan> executedInvoices = invoicePlans.stream() List<OmsReceivableInvoicePlan> executedInvoices = invoicePlans.stream()
.filter(p -> p.getDetailId() != null).collect(Collectors.toList()); .filter(p -> p.getDetailId() != null).collect(Collectors.toList());
@ -245,7 +245,7 @@ public class OmsReceivableReceiptPlanServiceImpl implements IOmsReceivableReceip
List<OmsReceivableInvoicePlan> finalPlans = new ArrayList<>(executedInvoices); List<OmsReceivableInvoicePlan> finalPlans = new ArrayList<>(executedInvoices);
finalPlans.addAll(newPlans); finalPlans.addAll(newPlans);
updateInvoicePlan(receivableBillId, finalPlans); invoicePlanService.updateInvoicePlans(receivableBillId, finalPlans);
} }
} }
@ -254,35 +254,7 @@ public class OmsReceivableReceiptPlanServiceImpl implements IOmsReceivableReceip
return omsReceivableReceiptPlanMapper.firstUnPayPlan(id); return omsReceivableReceiptPlanMapper.firstUnPayPlan(id);
} }
/**
*
*
* @param receivableBillId ID
* @param invoicePlanList
*/
private void updateInvoicePlan(Long receivableBillId, List<OmsReceivableInvoicePlan> invoicePlanList) {
// 删除原有的开票计划
OmsReceivableInvoicePlan invoicePlanCriteria = new OmsReceivableInvoicePlan();
invoicePlanCriteria.setReceivableBillId(receivableBillId);
List<OmsReceivableInvoicePlan> existingPlans = invoicePlanService.selectOmsReceivableInvoicePlanList(invoicePlanCriteria);
// Collect IDs of existing plans to delete them
if (!existingPlans.isEmpty()) {
String ids = existingPlans.stream()
.map(plan -> plan.getId().toString())
.reduce((a, b) -> a + "," + b)
.orElse("");
if (!ids.isEmpty()) {
invoicePlanService.deleteOmsReceivableInvoicePlanByIds(ids);
}
}
// 批量插入新的开票计划
for (OmsReceivableInvoicePlan plan : invoicePlanList) {
plan.setReceivableBillId(receivableBillId);
invoicePlanService.insertOmsReceivableInvoicePlan(plan);
}
}
private List<OmsReceivableInvoicePlan> convertReceiptToInvoice(List<OmsReceivableReceiptPlan> receiptPlans, Long receivableBillId) { private List<OmsReceivableInvoicePlan> convertReceiptToInvoice(List<OmsReceivableReceiptPlan> receiptPlans, Long receivableBillId) {
List<OmsReceivableInvoicePlan> list = new ArrayList<>(); List<OmsReceivableInvoicePlan> list = new ArrayList<>();

View File

@ -42,6 +42,7 @@ import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.dto.HomepageQueryDto; import com.ruoyi.sip.dto.HomepageQueryDto;
import com.ruoyi.sip.dto.OrderExcelNumStaticsDto; import com.ruoyi.sip.dto.OrderExcelNumStaticsDto;
import com.ruoyi.sip.dto.StatisticsDetailDto; import com.ruoyi.sip.dto.StatisticsDetailDto;
import com.ruoyi.sip.flowable.service.IBuApproveConfigService;
import com.ruoyi.sip.mapper.OmsStockInfoMapper; import com.ruoyi.sip.mapper.OmsStockInfoMapper;
import com.ruoyi.sip.mapper.ProjectInfoMapper; import com.ruoyi.sip.mapper.ProjectInfoMapper;
import com.ruoyi.sip.service.*; import com.ruoyi.sip.service.*;
@ -50,6 +51,7 @@ import com.ruoyi.sip.flowable.service.TodoCommonTemplate;
import com.ruoyi.sip.flowable.service.TodoService; import com.ruoyi.sip.flowable.service.TodoService;
import com.ruoyi.common.utils.mail.TemplateMailUtil; import com.ruoyi.common.utils.mail.TemplateMailUtil;
import com.ruoyi.sip.vo.OrderInfoVo; import com.ruoyi.sip.vo.OrderInfoVo;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
@ -61,6 +63,7 @@ import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task; import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.ruoyi.sip.mapper.ProjectOrderInfoMapper; import com.ruoyi.sip.mapper.ProjectOrderInfoMapper;
import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.core.text.Convert;
@ -131,6 +134,13 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
private Integer endHour; private Integer endHour;
@Value("${unis.mail.businessRoleId:103}") @Value("${unis.mail.businessRoleId:103}")
private String businessRoleId; private String businessRoleId;
@Autowired
private ISysConfigService configService;
@Autowired
@Lazy
private IBuApproveConfigService approveConfigService;
/** /**
* *
* *
@ -430,12 +440,15 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
String orderFlowKey = ProjectOrderInfo.ProcessTypeEnum.ONLINE.getCode().equals(projectOrderInfo.getProcessType()) ? String orderFlowKey = ProjectOrderInfo.ProcessTypeEnum.ONLINE.getCode().equals(projectOrderInfo.getProcessType()) ?
orderOnlineFlowKey : orderOfflineFlowKey; orderOnlineFlowKey : orderOfflineFlowKey;
String amountConfig = configService.selectConfigByKey("order.approve.amount.config");
BigDecimal amountConfigNumber = new BigDecimal(amountConfig);
//启动流程 //启动流程
todoService.startProcess(getFlowBusinessKey(existProjectOrderInfo.getOrderCode(), projectOrderInfo.getProcessType()), new HashMap<String, Object>() {{ todoService.startProcess(getFlowBusinessKey(existProjectOrderInfo.getOrderCode(), projectOrderInfo.getProcessType()), new HashMap<String, Object>() {{
put("processTemplate", projectOrderInfo.getProcessTemplate()); put("processTemplate", projectOrderInfo.getProcessTemplate());
put("processType", projectOrderInfo.getProcessType()); put("processType", projectOrderInfo.getProcessType());
put("applyUserName", ShiroUtils.getSysUser().getUserName()); put("applyUserName", ShiroUtils.getSysUser().getUserName());
put("applyUser", ShiroUtils.getUserId()); put("applyUser", ShiroUtils.getUserId());
put("skipLeader",projectOrderInfo.getShipmentAmount().compareTo(amountConfigNumber)<0);
put("partnerUser",partnerInfos.get(0).getSystemUserId()); put("partnerUser",partnerInfos.get(0).getSystemUserId());
put("extendField1", projectOrderInfo.getVersionCode()); put("extendField1", projectOrderInfo.getVersionCode());
}}, orderFlowKey); }}, orderFlowKey);
@ -1174,7 +1187,26 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
handleBusinessApproval(businessKey); handleBusinessApproval(businessKey);
} else if ("省代".equals(taskName)) { } else if ("省代".equals(taskName)) {
handlePartnerApproval(businessKey); handlePartnerApproval(businessKey);
} else if ("公司领导".equals(taskName)) { } else if ("领导1".equals(taskName) && todo.getApplyTime().compareTo(DateUtils.parseDate("2025-12-19"))>0){
ProjectOrderInfo orderInfo = selectProjectOrderInfoByOrderCode(businessKey);
String amountConfig = configService.selectConfigByKey("order.approve.amount.config");
BigDecimal amountConfigNumber = new BigDecimal(amountConfig);
if (orderInfo.getShipmentAmount().compareTo(amountConfigNumber)<0){
handleCompanyLeaderApproval(businessKey);
//查询对应的数据 插入已办数据
List<Long> approveUserList = approveConfigService.listByProcessKeyAndTaskName(todo.getProcessKey(), "公司领导");
for (Long l : approveUserList) {
todoService.completed(new HashMap<>(), todo.getTaskId(), businessKey);
todo.setApproveUser(l.toString());
todo.setTaskName("公司领导");
todo.setApproveUserName(userService.selectUserById(l).getUserName());
todo.setApproveOpinion("默认审批");
todo.setNextAllApproveUserName(null);
todo.setAllApproveUserName(null);
todoService.insertTodoCompleted(Arrays.asList(todo));
}
}
}else if ("公司领导".equals(taskName)) {
//黄雪秋处理 流程状态更改 //黄雪秋处理 流程状态更改
if (ShiroUtils.getUserId().equals(118L)) { if (ShiroUtils.getUserId().equals(118L)) {
@ -1559,8 +1591,11 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
query.setProcessKeyList(Arrays.asList(orderOnlineFlowKey,orderOfflineFlowKey)); query.setProcessKeyList(Arrays.asList(orderOnlineFlowKey,orderOfflineFlowKey));
List<Todo> list = todoService.selectTodoList(query); List<Todo> list = todoService.selectTodoList(query);
for (Todo todo1 : list) { for (Todo todo1 : list) {
Map<String, Object> temp = new HashMap<>();
todo1.setVariables(new HashMap<>(todo.getVariables())); for (Map.Entry<String, Object> entry : todo.getVariables().entrySet()) {
temp.put(entry.getKey(), new String(entry.getValue().toString()));
}
todo1.setVariables(temp);
approveOrder(todo1); approveOrder(todo1);
} }
} }

View File

@ -1,106 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.sip.mapper.OmsInvoiceReceiptBillMapper">
<resultMap type="OmsInvoiceReceiptBill" id="OmsInvoiceReceiptBillResult">
<result property="id" column="id" />
<result property="invoiceReceiptBillCode" column="invoice_receipt_bill_code" />
<result property="vendorCode" column="vendor_code" />
<result property="orderCode" column="order_code" />
<result property="totalPriceWithTax" column="total_price_with_tax" />
<result property="totalPriceWithoutTax" column="total_price_without_tax" />
<result property="taxAmount" column="tax_amount" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
<result property="delFlag" column="del_flag" />
</resultMap>
<sql id="selectOmsInvoiceReceiptBillVo">
select id, invoice_receipt_bill_code, vendor_code, order_code, total_price_with_tax, total_price_without_tax, tax_amount, create_by, create_time, update_by, update_time, remark, del_flag from oms_invoice_receipt_bill
</sql>
<select id="selectOmsInvoiceReceiptBillList" parameterType="OmsInvoiceReceiptBill" resultMap="OmsInvoiceReceiptBillResult">
<include refid="selectOmsInvoiceReceiptBillVo"/>
<where>
<if test="invoiceReceiptBillCode != null and invoiceReceiptBillCode != ''"> and invoice_receipt_bill_code = #{invoiceReceiptBillCode}</if>
<if test="vendorCode != null and vendorCode != ''"> and vendor_code = #{vendorCode}</if>
<if test="orderCode != null and orderCode != ''"> and order_code = #{orderCode}</if>
<if test="totalPriceWithTax != null "> and total_price_with_tax = #{totalPriceWithTax}</if>
<if test="totalPriceWithoutTax != null "> and total_price_without_tax = #{totalPriceWithoutTax}</if>
<if test="taxAmount != null "> and tax_amount = #{taxAmount}</if>
</where>
</select>
<select id="selectOmsInvoiceReceiptBillById" parameterType="Long" resultMap="OmsInvoiceReceiptBillResult">
<include refid="selectOmsInvoiceReceiptBillVo"/>
where id = #{id}
</select>
<insert id="insertOmsInvoiceReceiptBill" parameterType="OmsInvoiceReceiptBill" useGeneratedKeys="true" keyProperty="id">
insert into oms_invoice_receipt_bill
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="invoiceReceiptBillCode != null and invoiceReceiptBillCode != ''">invoice_receipt_bill_code,</if>
<if test="vendorCode != null">vendor_code,</if>
<if test="orderCode != null">order_code,</if>
<if test="totalPriceWithTax != null">total_price_with_tax,</if>
<if test="totalPriceWithoutTax != null">total_price_without_tax,</if>
<if test="taxAmount != null">tax_amount,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="remark != null">remark,</if>
<if test="delFlag != null">del_flag,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="invoiceReceiptBillCode != null and invoiceReceiptBillCode != ''">#{invoiceReceiptBillCode},</if>
<if test="vendorCode != null">#{vendorCode},</if>
<if test="orderCode != null">#{orderCode},</if>
<if test="totalPriceWithTax != null">#{totalPriceWithTax},</if>
<if test="totalPriceWithoutTax != null">#{totalPriceWithoutTax},</if>
<if test="taxAmount != null">#{taxAmount},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="remark != null">#{remark},</if>
<if test="delFlag != null">#{delFlag},</if>
</trim>
</insert>
<update id="updateOmsInvoiceReceiptBill" parameterType="OmsInvoiceReceiptBill">
update oms_invoice_receipt_bill
<trim prefix="SET" suffixOverrides=",">
<if test="invoiceReceiptBillCode != null and invoiceReceiptBillCode != ''">invoice_receipt_bill_code = #{invoiceReceiptBillCode},</if>
<if test="vendorCode != null">vendor_code = #{vendorCode},</if>
<if test="orderCode != null">order_code = #{orderCode},</if>
<if test="totalPriceWithTax != null">total_price_with_tax = #{totalPriceWithTax},</if>
<if test="totalPriceWithoutTax != null">total_price_without_tax = #{totalPriceWithoutTax},</if>
<if test="taxAmount != null">tax_amount = #{taxAmount},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteOmsInvoiceReceiptBillById" parameterType="Long">
delete from oms_invoice_receipt_bill where id = #{id}
</delete>
<delete id="deleteOmsInvoiceReceiptBillByIds" parameterType="String">
delete from oms_invoice_receipt_bill where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -39,7 +39,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach> </foreach>
</if> </if>
<if test="productSn != null and productSn != ''">and t1.product_sn = #{productSn}</if> <if test="productSn != null and productSn != ''">and t1.product_sn = #{productSn}</if>
<if test="productSnList != null and productSnList != ''">and t1.product_sn in <if test="productSnList != null and productSnList.size>0">and t1.product_sn in
<foreach item="item" index="index" collection="productSnList" separator="," open="(" close=")"> <foreach item="item" index="index" collection="productSnList" separator="," open="(" close=")">
#{item} #{item}
</foreach> </foreach>

View File

@ -0,0 +1,398 @@
<?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.OmsInvoiceBillMapper">
<resultMap type="com.ruoyi.sip.domain.OmsInvoiceBill" id="OmsInvoiceBillResult">
<result property="id" column="id" />
<result property="invoiceBillCode" column="invoice_bill_code" />
<result property="invoiceType" column="invoice_type" />
<result property="invoiceBillType" column="invoice_bill_type" />
<result property="invoiceTime" column="invoice_time" />
<result property="partnerCode" column="partner_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="actualInvoiceTime" column="actual_invoice_time" />
<result property="invoiceStatus" column="invoice_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" />
<result property="originalBillId" column="original_bill_id" />
</resultMap>
<sql id="selectOmsInvoiceBillVo">
select id, invoice_bill_code, invoice_type, invoice_bill_type,
invoice_time, partner_code, total_price_with_tax, total_price_without_tax,
tax_rate, create_by, create_time, update_by, update_time,
remark, del_flag, actual_invoice_time, invoice_status,
approve_status, approve_time, refund_status
, original_bill_id
from oms_invoice_bill
</sql>
<select id="selectOmsInvoiceBillList" parameterType="com.ruoyi.sip.domain.OmsInvoiceBill" resultMap="OmsInvoiceBillResult">
<include refid="selectOmsInvoiceBillVo"/>
<where>
<if test="invoiceBillCode != null and invoiceBillCode != ''">
and invoice_bill_code = #{invoiceBillCode}
</if>
<if test="invoiceType != null and invoiceType != ''">
and invoice_type = #{invoiceType}
</if>
<if test="invoiceBillType != null and invoiceBillType != ''">
and invoice_bill_type = #{invoiceBillType}
</if>
<if test="invoiceTime != null ">
and invoice_time = #{invoiceTime}
</if>
<if test="partnerCode != null and partnerCode != ''">
and partner_code = #{partnerCode}
</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 = #{remark}
</if>
<if test="delFlag != null and delFlag != ''">
and del_flag = #{delFlag}
</if>
<if test="actualInvoiceTime != null ">
and actual_invoice_time = #{actualInvoiceTime}
</if>
<if test="invoiceStatus != null and invoiceStatus != ''">
and invoice_status = #{invoiceStatus}
</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>
<if test="originalBillId != null ">
and original_bill_id = #{originalBillId}
</if>
</where>
</select>
<select id="selectOmsInvoiceBillById" parameterType="Long" resultMap="OmsInvoiceBillResult">
<include refid="selectOmsInvoiceBillVo"/>
where id = #{id}
</select>
<insert id="insertOmsInvoiceBill" parameterType="com.ruoyi.sip.domain.OmsInvoiceBill" useGeneratedKeys="true" keyProperty="id">
insert into oms_invoice_bill
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="invoiceBillCode != null and invoiceBillCode != ''">
invoice_bill_code,
</if>
<if test="invoiceType != null and invoiceType != ''">
invoice_type,
</if>
<if test="invoiceBillType != null and invoiceBillType != ''">
invoice_bill_type,
</if>
<if test="invoiceTime != null">
invoice_time,
</if>
<if test="partnerCode != null and partnerCode != ''">
partner_code,
</if>
<if test="partnerName != null and partnerName != ''">
partner_name,
</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="actualInvoiceTime != null">
actual_invoice_time,
</if>
<if test="invoiceStatus != null and invoiceStatus != ''">
invoice_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>
<if test="originalBillId != null">
original_bill_id,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="invoiceBillCode != null and invoiceBillCode != ''">
#{invoiceBillCode},
</if>
<if test="invoiceType != null and invoiceType != ''">
#{invoiceType},
</if>
<if test="invoiceBillType != null and invoiceBillType != ''">
#{invoiceBillType},
</if>
<if test="invoiceTime != null">
#{invoiceTime},
</if>
<if test="partnerCode != null and partnerCode != ''">
#{partnerCode},
</if>
<if test="partnerName != null and partnerName != ''">
#{partnerName},
</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="actualInvoiceTime != null">
#{actualInvoiceTime},
</if>
<if test="invoiceStatus != null and invoiceStatus != ''">
#{invoiceStatus},
</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>
<if test="originalBillId != null">
#{originalBillId},
</if>
</trim>
</insert>
<update id="updateOmsInvoiceBill" parameterType="com.ruoyi.sip.domain.OmsInvoiceBill">
update oms_invoice_bill
<trim prefix="SET" suffixOverrides=",">
<if test="invoiceBillCode != null and invoiceBillCode != ''">
invoice_bill_code = #{invoiceBillCode},
</if>
<if test="invoiceType != null and invoiceType != ''">
invoice_type = #{invoiceType},
</if>
<if test="invoiceBillType != null and invoiceBillType != ''">
invoice_bill_type = #{invoiceBillType},
</if>
<if test="invoiceTime != null">
invoice_time = #{invoiceTime},
</if>
<if test="partnerCode != null and partnerCode != ''">
partner_code = #{partnerCode},
</if>
<if test="totalPriceWithTax != null">
total_price_with_tax = #{totalPriceWithTax},
</if>
<if test="totalPriceWithoutTax != null">
total_price_without_tax = #{totalPriceWithoutTax},
</if>
<if test="taxRate != null">
tax_rate = #{taxRate},
</if>
<if test="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="actualInvoiceTime != null">
actual_invoice_time = #{actualInvoiceTime},
</if>
<if test="invoiceStatus != null and invoiceStatus != ''">
invoice_status = #{invoiceStatus},
</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>
<if test="originalBillId != null">
original_bill_id = #{originalBillId},
</if>
</trim>
where id = #{id}
</update>
<update id="updateOmsInvoiceBillByCode" parameterType="com.ruoyi.sip.domain.OmsInvoiceBill">
update oms_invoice_bill
<trim prefix="SET" suffixOverrides=",">
<if test="invoiceStatus != null and invoiceStatus != ''">
invoice_status = #{invoiceStatus},
</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="actualInvoiceTime != null">
actual_invoice_time = #{actualInvoiceTime},
</if>
<if test="refundStatus != null and refundStatus != ''">
refund_status = #{refundStatus},
</if>
</trim>
where invoice_bill_code = #{invoiceBillCode}
</update>
<delete id="deleteOmsInvoiceBillById" parameterType="Long">
delete from oms_invoice_bill where id = #{id}
</delete>
<delete id="deleteOmsInvoiceBillByIds" parameterType="String">
delete from oms_invoice_bill where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<delete id="clearRelationReceivable">
delete from oms_receivable_invoice_detail where invoice_bill_code=#{code}
</delete>
<select id="listApprove" resultType="com.ruoyi.sip.domain.OmsInvoiceBill">
select t1.* from oms_invoice_bill t1
left join ${tablename} t2 on t1.invoice_bill_code = t2.business_key
where 1=1
<if test="omsInvoiceBill.invoiceBillCode != null and omsInvoiceBill.invoiceBillCode != ''">
and t1.invoice_bill_code = #{omsInvoiceBill.invoiceBillCode}
</if>
<if test="omsInvoiceBill.partnerCode != null and omsInvoiceBill.partnerCode != ''">
and t1.partner_code = #{omsInvoiceBill.partnerCode}
</if>
<if test="omsInvoiceBill.approveUser != null">
and t2.assignee_user_id = #{omsInvoiceBill.approveUser}
</if>
order by t1.create_time desc
</select>
<select id="selectOmsInvoiceBillByCode" resultType="com.ruoyi.sip.domain.OmsInvoiceBill">
<include refid="selectOmsInvoiceBillVo"/>
where invoice_bill_code = #{invoiceBillCode} and del_flag = '0'
</select>
<select id="selectMaxCodeByPrefix" resultType="java.lang.Integer">
select COALESCE(MAX(CAST(SUBSTRING(invoice_bill_code, #{codePrefix.length() + 1}) AS UNSIGNED)), 0)
from oms_invoice_bill
where invoice_bill_code LIKE CONCAT(#{codePrefix}, '%')
</select>
</mapper>

View File

@ -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.OmsPayableTicketWriteOffMapper">
<resultMap type="com.ruoyi.sip.domain.OmsPayableTicketWriteOff" id="OmsPayableTicketWriteOffResult">
<result property="id" column="id" />
<result property="writeOffCode" column="write_off_code" />
<result property="writeOffType" column="write_off_type" />
<result property="ticketBillCode" column="ticket_bill_code" />
<result property="vendorCode" column="vendor_code" />
<result property="writeOffAmount" column="write_off_amount" />
<result property="writeOffAmountWithoutTax" column="write_off_amount_without_tax" />
<result property="writeOffTaxAmount" column="write_off_tax_amount" />
<result property="writeOffTime" column="write_off_time" />
<result property="remark" column="remark" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectOmsPayableTicketWriteOffVo">
select t1.id, t1.write_off_code, t1.write_off_type, t1.ticket_bill_code, t1.vendor_code,
t1.write_off_amount, t1.write_off_amount_without_tax, t1.write_off_tax_amount,
t1.write_off_time, t1.remark, t1.create_by, t1.create_time, t1.update_by, t1.update_time,
t3.user_name as create_by_name,t2.vendor_name
from oms_payable_ticket_write_off t1
left join oms_vendor_info t2 on t1.vendor_code = t2.vendor_code
left join sys_user t3 on t1.create_by = t3.user_id
</sql>
<select id="selectOmsPayableTicketWriteOffById" parameterType="Long" resultMap="OmsPayableTicketWriteOffResult">
<include refid="selectOmsPayableTicketWriteOffVo"/>
where t1.id = #{id}
</select>
<select id="selectOmsPayableTicketWriteOffList" parameterType="com.ruoyi.sip.domain.OmsPayableTicketWriteOff" resultMap="OmsPayableTicketWriteOffResult">
<include refid="selectOmsPayableTicketWriteOffVo"/>
<where>
<if test="writeOffCode != null and writeOffCode != ''">
and t1.write_off_code = #{writeOffCode}
</if>
<if test="writeOffType != null and writeOffType != ''">
and t1.write_off_type = #{writeOffType}
</if>
<if test="ticketBillCode != null and ticketBillCode != ''">
and t1.ticket_bill_code = #{ticketBillCode}
</if>
<if test="vendorCode != null and vendorCode != ''">
and t1.vendor_code = #{vendorCode}
</if>
<if test="writeOffAmount != null">
and t1.write_off_amount = #{writeOffAmount}
</if>
<if test="writeOffAmountWithoutTax != null">
and t1.write_off_amount_without_tax = #{writeOffAmountWithoutTax}
</if>
<if test="writeOffTaxAmount != null">
and t1.write_off_tax_amount = #{writeOffTaxAmount}
</if>
<if test="writeOffTime != null">
and t1.write_off_time = #{writeOffTime}
</if>
<if test="remark != null and remark != ''">
and t1.remark like concat('%', #{remark}, '%')
</if>
<if test="createBy != null and createBy != ''">
and t1.create_by = #{createBy}
</if>
<if test="createTime != null">
and t1.create_time = #{createTime}
</if>
<if test="updateBy != null and updateBy != ''">
and t1.update_by = #{updateBy}
</if>
<if test="updateTime != null">
and t1.update_time = #{updateTime}
</if>
</where>
</select>
<insert id="insertOmsPayableTicketWriteOff" parameterType="com.ruoyi.sip.domain.OmsPayableTicketWriteOff" useGeneratedKeys="true" keyProperty="id">
insert into oms_payable_ticket_write_off
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="writeOffCode != null and writeOffCode != ''">
write_off_code,
</if>
<if test="writeOffType != null and writeOffType != ''">
write_off_type,
</if>
<if test="ticketBillCode != null and ticketBillCode != ''">
ticket_bill_code,
</if>
<if test="vendorCode != null and vendorCode != ''">
vendor_code,
</if>
<if test="writeOffAmount != null">
write_off_amount,
</if>
<if test="writeOffAmountWithoutTax != null">
write_off_amount_without_tax,
</if>
<if test="writeOffTaxAmount != null">
write_off_tax_amount,
</if>
<if test="writeOffTime != null">
write_off_time,
</if>
<if test="remark != null and remark != ''">
remark,
</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="writeOffCode != null and writeOffCode != ''">
#{writeOffCode},
</if>
<if test="writeOffType != null and writeOffType != ''">
#{writeOffType},
</if>
<if test="ticketBillCode != null and ticketBillCode != ''">
#{ticketBillCode},
</if>
<if test="vendorCode != null and vendorCode != ''">
#{vendorCode},
</if>
<if test="writeOffAmount != null">
#{writeOffAmount},
</if>
<if test="writeOffAmountWithoutTax != null">
#{writeOffAmountWithoutTax},
</if>
<if test="writeOffTaxAmount != null">
#{writeOffTaxAmount},
</if>
<if test="writeOffTime != null">
#{writeOffTime},
</if>
<if test="remark != null and remark != ''">
#{remark},
</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="updateOmsPayableTicketWriteOff" parameterType="com.ruoyi.sip.domain.OmsPayableTicketWriteOff">
update oms_payable_ticket_write_off
<trim prefix="SET" suffixOverrides=",">
<if test="writeOffCode != null and writeOffCode != ''">
write_off_code = #{writeOffCode},
</if>
<if test="writeOffType != null and writeOffType != ''">
write_off_type = #{writeOffType},
</if>
<if test="ticketBillCode != null and ticketBillCode != ''">
ticket_bill_code = #{ticketBillCode},
</if>
<if test="vendorCode != null and vendorCode != ''">
vendor_code = #{vendorCode},
</if>
<if test="writeOffAmount != null">
write_off_amount = #{writeOffAmount},
</if>
<if test="writeOffAmountWithoutTax != null">
write_off_amount_without_tax = #{writeOffAmountWithoutTax},
</if>
<if test="writeOffTaxAmount != null">
write_off_tax_amount = #{writeOffTaxAmount},
</if>
<if test="writeOffTime != null">
write_off_time = #{writeOffTime},
</if>
<if test="remark != null and remark != ''">
remark = #{remark},
</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="deleteOmsPayableTicketWriteOffById" parameterType="Long">
delete from oms_payable_ticket_write_off where id = #{id}
</delete>
<delete id="deleteOmsPayableTicketWriteOffByIds" parameterType="String">
delete from oms_payable_ticket_write_off where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<select id="listByIds" parameterType="String" resultMap="OmsPayableTicketWriteOffResult">
<include refid="selectOmsPayableTicketWriteOffVo"/>
where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<select id="selectMaxCodeByPrefix" parameterType="String" resultType="java.lang.Integer">
SELECT COALESCE(MAX(CAST(SUBSTRING(write_off_code, LENGTH(#{codePrefix}) + 1) AS UNSIGNED)), 0)
FROM oms_payable_ticket_write_off
WHERE write_off_code LIKE CONCAT(#{codePrefix}, '%')
</select>
</mapper>

View File

@ -35,11 +35,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.total_price_with_tax, t1.total_price_without_tax, t1.tax_rate, t1.tax_amount, t1.received_amount, t1.unreceived_amount, t1.total_price_with_tax, t1.total_price_without_tax, t1.tax_rate, t1.tax_amount, t1.received_amount, t1.unreceived_amount,
t1.invoiced_amount, t1.uninvoiced_amount, t1.create_by, t1.create_time, t1.update_by, t1.update_time, t1.remark, t1.del_flag t1.invoiced_amount, t1.uninvoiced_amount, t1.create_by, t1.create_time, t1.update_by, t1.update_time, t1.remark, t1.del_flag
,t3.project_name, t3.project_code ,t3.project_name, t3.project_code
,t4.plan_amount,t4.plan_receipt_date ,t4.plan_amount,t4.plan_receipt_date,
t5.plan_amount as plan_invoice_amount, t5.plan_invoice_date
from oms_receivable_bill t1 from oms_receivable_bill t1
left join project_order_info t2 on t1.order_code=t2.order_code left join project_order_info t2 on t1.order_code=t2.order_code
left join project_info t3 on t2.project_id=t3.id left join project_info t3 on t2.project_id=t3.id
left join oms_receivable_receipt_plan t4 on t1.last_receipt_plan_id=t4.id left join oms_receivable_receipt_plan t4 on t1.last_receipt_plan_id=t4.id
left join oms_receivable_invoice_plan t5 on t1.last_invoice_plan_id=t5.id
</sql> </sql>
<select id="selectOmsReceivableBillById" parameterType="Long" resultMap="OmsReceivableBillResult"> <select id="selectOmsReceivableBillById" parameterType="Long" resultMap="OmsReceivableBillResult">

View File

@ -10,9 +10,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="receivableBillId" column="receivable_bill_id" /> <result property="receivableBillId" column="receivable_bill_id" />
<result property="invoiceTime" column="invoice_time" /> <result property="invoiceTime" column="invoice_time" />
<result property="invoiceAmount" column="invoice_amount" /> <result property="invoiceAmount" column="invoice_amount" />
<result property="invoiceAmountWithoutTax" column="invoice_amount_without_tax" />
<result property="invoiceAmountTax" column="invoice_amount_tax" />
<result property="invoiceRate" column="invoice_rate" /> <result property="invoiceRate" column="invoice_rate" />
<result property="invoiceBillCode" column="invoice_bill_code" /> <result property="invoiceBillCode" column="invoice_bill_code" />
<result property="remark" column="remark" /> <result property="remark" column="remark" />
<result property="receivableDetailType" column="receivable_detail_type" />
<result property="createTime" column="create_time" /> <result property="createTime" column="create_time" />
<result property="createBy" column="create_by" /> <result property="createBy" column="create_by" />
<result property="updateTime" column="update_time" /> <result property="updateTime" column="update_time" />
@ -20,7 +24,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap> </resultMap>
<sql id="selectOmsReceivableInvoiceDetailVo"> <sql id="selectOmsReceivableInvoiceDetailVo">
select id, invoice_plan_id, receivable_bill_id, invoice_time, invoice_amount, invoice_rate, invoice_bill_code, remark, create_time, create_by, update_time, update_by select id, invoice_plan_id, receivable_bill_id, invoice_time, invoice_amount, invoice_amount_without_tax, invoice_amount_tax, invoice_rate, invoice_bill_code, remark, receivable_detail_type, create_time, create_by, update_time, update_by
from oms_receivable_invoice_detail from oms_receivable_invoice_detail
</sql> </sql>
@ -36,26 +40,38 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="receivableBillId != null "> and receivable_bill_id = #{receivableBillId}</if> <if test="receivableBillId != null "> and receivable_bill_id = #{receivableBillId}</if>
<if test="invoiceTime != null "> and invoice_time = #{invoiceTime}</if> <if test="invoiceTime != null "> and invoice_time = #{invoiceTime}</if>
<if test="invoiceAmount != null "> and invoice_amount = #{invoiceAmount}</if> <if test="invoiceAmount != null "> and invoice_amount = #{invoiceAmount}</if>
<if test="invoiceAmountWithoutTax != null "> and invoice_amount_without_tax = #{invoiceAmountWithoutTax}</if>
<if test="invoiceAmountTax != null "> and invoice_amount_tax = #{invoiceAmountTax}</if>
<if test="invoiceRate != null "> and invoice_rate = #{invoiceRate}</if> <if test="invoiceRate != null "> and invoice_rate = #{invoiceRate}</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''"> and invoice_bill_code = #{invoiceBillCode}</if> <if test="invoiceBillCode != null and invoiceBillCode != ''"> and invoice_bill_code = #{invoiceBillCode}</if>
<if test="receivableDetailType != null and receivableDetailType != ''"> and receivable_detail_type = #{receivableDetailType}</if>
<if test="remark != null and remark != ''"> and remark like concat('%', #{remark}, '%')</if> <if test="remark != null and remark != ''"> and remark like concat('%', #{remark}, '%')</if>
</where> </where>
</select> </select>
<select id="listByReceivableBillIdList" resultType="com.ruoyi.sip.domain.OmsReceivableInvoiceDetail"> <select id="list" resultType="com.ruoyi.sip.domain.OmsReceivableInvoiceDetail">
select SELECT
<include refid="selectOmsReceivableInvoiceDetailVo"/> t1.*,t2.invoice_bill_code,t2.actual_invoice_time,t2.invoice_status,t2.id as invoice_bill_id
FROM
oms_receivable_invoice_detail t1
LEFT JOIN oms_invoice_bill t2 ON t1.invoice_bill_code = t2.invoice_bill_code
<where> <where>
<if test="list != null and list.size() > 0"> <if test="receivableBillIdList != null and receivableBillIdList.size() > 0">
and receivable_bill_id in and t1.receivable_bill_id in
<foreach item="item" collection="list" separator="," open="(" close=")" index="index"> <foreach item="item" collection="receivableBillIdList" separator="," open="(" close=")" index="index">
#{item} #{item}
</foreach> </foreach>
</if> </if>
<if test="receivableBillId != null ">
and t1.receivable_bill_id =#{receivableBillId}
</if>
<if test="invoiceBillCode != null ">
and t1.invoice_bill_code =#{invoiceBillCode}
</if>
</where> </where>
</select> </select>
<select id="selectByInvoicePlanIds" resultType="com.ruoyi.sip.domain.OmsReceivableInvoiceDetail"> <select id="selectByInvoicePlanIds" resultType="com.ruoyi.sip.domain.OmsReceivableInvoiceDetail">
select
<include refid="selectOmsReceivableInvoiceDetailVo"/> <include refid="selectOmsReceivableInvoiceDetailVo"/>
<where> <where>
<if test="list != null and list.size() > 0"> <if test="list != null and list.size() > 0">
@ -75,8 +91,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="receivableBillId != null">receivable_bill_id,</if> <if test="receivableBillId != null">receivable_bill_id,</if>
<if test="invoiceTime != null">invoice_time,</if> <if test="invoiceTime != null">invoice_time,</if>
<if test="invoiceAmount != null">invoice_amount,</if> <if test="invoiceAmount != null">invoice_amount,</if>
<if test="invoiceAmountWithoutTax != null">invoice_amount_without_tax,</if>
<if test="invoiceAmountTax != null">invoice_amount_tax,</if>
<if test="invoiceRate != null">invoice_rate,</if> <if test="invoiceRate != null">invoice_rate,</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''">invoice_bill_code,</if> <if test="invoiceBillCode != null and invoiceBillCode != ''">invoice_bill_code,</if>
<if test="receivableDetailType != null and receivableDetailType != ''">receivable_detail_type,</if>
<if test="remark != null and remark != ''">remark,</if> <if test="remark != null and remark != ''">remark,</if>
<if test="createTime != null">create_time,</if> <if test="createTime != null">create_time,</if>
<if test="createBy != null and createBy != ''">create_by,</if> <if test="createBy != null and createBy != ''">create_by,</if>
@ -88,8 +108,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="receivableBillId != null">#{receivableBillId},</if> <if test="receivableBillId != null">#{receivableBillId},</if>
<if test="invoiceTime != null">#{invoiceTime},</if> <if test="invoiceTime != null">#{invoiceTime},</if>
<if test="invoiceAmount != null">#{invoiceAmount},</if> <if test="invoiceAmount != null">#{invoiceAmount},</if>
<if test="invoiceAmountWithoutTax != null">#{invoiceAmountWithoutTax},</if>
<if test="invoiceAmountTax != null">#{invoiceAmountTax},</if>
<if test="invoiceRate != null">#{invoiceRate},</if> <if test="invoiceRate != null">#{invoiceRate},</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''">#{invoiceBillCode},</if> <if test="invoiceBillCode != null and invoiceBillCode != ''">#{invoiceBillCode},</if>
<if test="receivableDetailType != null and receivableDetailType != ''">#{receivableDetailType},</if>
<if test="remark != null and remark != ''">#{remark},</if> <if test="remark != null and remark != ''">#{remark},</if>
<if test="createTime != null">#{createTime},</if> <if test="createTime != null">#{createTime},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if> <if test="createBy != null and createBy != ''">#{createBy},</if>
@ -105,8 +129,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="receivableBillId != null">receivable_bill_id = #{receivableBillId},</if> <if test="receivableBillId != null">receivable_bill_id = #{receivableBillId},</if>
<if test="invoiceTime != null">invoice_time = #{invoiceTime},</if> <if test="invoiceTime != null">invoice_time = #{invoiceTime},</if>
<if test="invoiceAmount != null">invoice_amount = #{invoiceAmount},</if> <if test="invoiceAmount != null">invoice_amount = #{invoiceAmount},</if>
<if test="invoiceAmountWithoutTax != null">invoice_amount_without_tax = #{invoiceAmountWithoutTax},</if>
<if test="invoiceAmountTax != null">invoice_amount_tax = #{invoiceAmountTax},</if>
<if test="invoiceRate != null">invoice_rate = #{invoiceRate},</if> <if test="invoiceRate != null">invoice_rate = #{invoiceRate},</if>
<if test="invoiceBillCode != null and invoiceBillCode != ''">invoice_bill_code = #{invoiceBillCode},</if> <if test="invoiceBillCode != null and invoiceBillCode != ''">invoice_bill_code = #{invoiceBillCode},</if>
<if test="receivableDetailType != null and receivableDetailType != ''">receivable_detail_type = #{receivableDetailType},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if> <if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="updateTime != null">update_time = #{updateTime},</if> <if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if> <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>