feat(finance): 新增申请开票功能模块
- 添加申请开票Vue组件,包含发票信息录入与提交逻辑 - 更新开票单详情抽屉展示字段及标签分类 - 扩展后端接口支持根据开票单号查询产品明细 - 新增申请开票API接口及前端调用服务 - 完善开票相关字典类型与状态显示 - 优化开票列表页字段展示与操作按钮布局 - 增加项目ID字段以支持更精确的产品关联 - 提供数字转中文大写金额转换功能 - 实现发票明细表格动态增删行与自动计算 - 引入电子发票类型选择与样式美化dev_1.0.1
parent
54e7d394bb
commit
fe2791f815
|
|
@ -0,0 +1,84 @@
|
|||
import request from '@/utils/request'
|
||||
import {tansParams} from "@/utils/ruoyi"
|
||||
|
||||
// 查询销售收票单列表
|
||||
export function listInvoice(query) {
|
||||
return request({
|
||||
url: '/finance/invoice/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询销售收票单详细
|
||||
export function getInvoice(id) {
|
||||
return request({
|
||||
url: '/finance/invoice/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询销售收票单附件
|
||||
export function getInvoiceAttachments(id, params) {
|
||||
return request({
|
||||
url: `/finance/invoice/attachment/${id}`,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 上传销售收票单附件
|
||||
export function uploadInvoiceAttachment(data) {
|
||||
return request({
|
||||
url: '/finance/invoice/uploadReceipt',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
},
|
||||
data: data,
|
||||
needLoading: true
|
||||
});
|
||||
}
|
||||
|
||||
// 申请红冲
|
||||
export function redRush(id) {
|
||||
return request({
|
||||
url: '/finance/invoice/applyRefund/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 退回销售收票单
|
||||
export function returnInvoice(id) {
|
||||
return request({
|
||||
url: '/finance/invoice/return/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增销售收票单
|
||||
export function addInvoice(data) {
|
||||
return request({
|
||||
url: '/finance/receivable/mergeAndInitiateInvoice',
|
||||
method: 'post',
|
||||
data: data,
|
||||
needLoading: true
|
||||
})
|
||||
}
|
||||
|
||||
// 查询销售收票单产品明细
|
||||
export function getInvoiceProducts(code) {
|
||||
return request({
|
||||
url: '/finance/invoice/product/' + code,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 申请开票
|
||||
export function applyInvoice(data) {
|
||||
return request({
|
||||
url: '/finance/invoice/apply',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,681 @@
|
|||
<template>
|
||||
<el-dialog title="申请开票" :visible.sync="visible" width="1000px" append-to-body @close="handleClose"
|
||||
custom-class="invoice-dialog">
|
||||
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="110px" class="invoice-form">
|
||||
|
||||
<!-- 1. 顶部:发票类型与票号日期 -->
|
||||
<div class="invoice-header">
|
||||
<div class="header-center">
|
||||
<div class="invoice-title">
|
||||
电子发票
|
||||
<span class="invoice-type-wrapper">
|
||||
(<el-select v-model="form.invoiceType" class="invoice-type-select" :popper-append-to-body="false">
|
||||
<el-option
|
||||
v-for="dict in dict.type.finance_invoice_type"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>)
|
||||
</span>
|
||||
</div>
|
||||
<div class="header-decoration-line"></div>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<div class="meta-row">
|
||||
<span class="meta-label">发票号码:</span>
|
||||
<span class="meta-value">----------</span>
|
||||
</div>
|
||||
<div class="meta-row">
|
||||
<span class="meta-label">开票日期:</span>
|
||||
<span class="meta-value">----------</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. 中部:购买方信息与销售方信息 -->
|
||||
<div class="invoice-body-border">
|
||||
<el-row type="flex" class="info-container">
|
||||
<!-- 左侧:购买方信息 -->
|
||||
<el-col :span="12" class="info-column left-column">
|
||||
<div class="column-label">购买方<br>信息</div>
|
||||
<div class="column-content">
|
||||
<el-form-item label="名称" prop="buyerName" class="condensed-item">
|
||||
<el-input v-model="form.buyerName" placeholder="请输入名称"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="统一社会信用代码/纳税人识别号" prop="buyerCreditCode"
|
||||
class="condensed-item label-wrap">
|
||||
<span slot="label" style="line-height: 1.2;">统一社会信用代码/<br>纳税人识别号</span>
|
||||
<el-input v-model="form.buyerCreditCode" placeholder="请输入纳税人识别号"/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<!-- 右侧:销售方信息 -->
|
||||
<el-col :span="12" class="info-column right-column">
|
||||
<div class="column-label">销售方<br>信息</div>
|
||||
<div class="column-content">
|
||||
<el-form-item label="名称" prop="sellerName" class="condensed-item">
|
||||
<el-input v-model="form.sellerName" placeholder="请输入名称"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="统一社会信用代码/纳税人识别号" prop="sellerCreditCode"
|
||||
class="condensed-item label-wrap">
|
||||
<span slot="label" style="line-height: 1.2;">统一社会信用代码/<br>纳税人识别号</span>
|
||||
<el-input v-model="form.sellerCreditCode" placeholder="请输入纳税人识别号"/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 3. 表格区域 -->
|
||||
<div class="items-table-container">
|
||||
<el-table
|
||||
:data="form.detailList"
|
||||
border
|
||||
height="250"
|
||||
class="invoice-table"
|
||||
show-summary
|
||||
:summary-method="getSummaries"
|
||||
>
|
||||
<el-table-column label="项目名称" prop="projectName" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.projectName" size="mini" placeholder="请输入" class="no-border-input"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产品型号" prop="productModel" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.productModel" size="mini" placeholder="型号" class="no-border-input"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价" prop="unitPrice" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.unitPrice" size="mini" @input="calculateAmount(scope.row)"
|
||||
class="no-border-input"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" prop="quantity" align="center" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.quantity" size="mini" @input="calculateAmount(scope.row)"
|
||||
class="no-border-input"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="金额" prop="amount" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.amount }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="税率%" prop="taxRate" align="center" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.taxRate" size="mini" @input="calculateTax(scope.row)"
|
||||
class="no-border-input"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="税额" prop="taxAmount" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.taxAmount }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="60" align="center">
|
||||
<template slot-scope="scope">
|
||||
<i class="el-icon-plus table-icon" @click="addDetailRow"
|
||||
v-if="scope.$index === form.detailList.length - 1"></i>
|
||||
<i class="el-icon-minus table-icon" @click="removeDetailRow(scope.$index)"
|
||||
v-if="form.detailList.length > 1" style="margin-left:5px"></i>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 4. 价税合计 -->
|
||||
<div class="total-row">
|
||||
<div class="total-label">价税合计 (大写)</div>
|
||||
<div class="total-value-chinese">
|
||||
<span class="currency-symbol">⊗</span> {{ totalAmountChinese }}
|
||||
</div>
|
||||
<div class="total-label-small">(小写)</div>
|
||||
<div class="total-value-number">
|
||||
¥{{ totalAmountNumber }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 5. 备注 -->
|
||||
<div class="remark-row">
|
||||
<div class="remark-label">备注</div>
|
||||
<div class="remark-content">
|
||||
<el-input type="textarea" :rows="2" v-model="form.remark" placeholder="请输入备注"
|
||||
class="no-border-textarea"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleClose">取 消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit" :loading="loading">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getInvoiceProducts, applyInvoice} from "@/api/finance/invoice";
|
||||
|
||||
export default {
|
||||
name: "ApplyInvoice",
|
||||
dicts: ['finance_invoice_type'],
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
form: {
|
||||
invoiceType: this.rowData.invoiceType || '-',
|
||||
buyerName: undefined,
|
||||
buyerCreditCode: undefined,
|
||||
sellerName: undefined,
|
||||
sellerCreditCode: undefined,
|
||||
remark: undefined,
|
||||
invoiceBillCode: this.rowData.invoiceBillCode,
|
||||
detailList: [
|
||||
{
|
||||
projectName: '',
|
||||
productModel: '',
|
||||
unit: '',
|
||||
unitPrice: '',
|
||||
quantity: '',
|
||||
amount: '',
|
||||
taxRate: '13',
|
||||
taxAmount: ''
|
||||
}
|
||||
]
|
||||
},
|
||||
rules: {
|
||||
invoiceType: [{required: true, message: "必填", trigger: "change"}],
|
||||
buyerName: [{required: true, message: "必填", trigger: "blur"}],
|
||||
buyerCreditCode: [{required: true, message: "必填", trigger: "blur"}],
|
||||
sellerName: [{required: true, message: "必填", trigger: "blur"}]
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
totalAmountNumber() {
|
||||
let total = 0;
|
||||
this.form.detailList.forEach(item => {
|
||||
const amount = parseFloat(item.amount) || 0;
|
||||
const tax = parseFloat(item.taxAmount) || 0;
|
||||
total += (amount + tax);
|
||||
});
|
||||
return total.toFixed(2);
|
||||
},
|
||||
totalAmountChinese() {
|
||||
return this.convertCurrency(this.totalAmountNumber);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible(val) {
|
||||
if (val) {
|
||||
this.reset();
|
||||
this.initData();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
reset() {
|
||||
this.form = {
|
||||
invoiceType: 'ELECTRONIC',
|
||||
buyerName: undefined,
|
||||
buyerCreditCode: undefined,
|
||||
sellerName: undefined,
|
||||
sellerCreditCode: undefined,
|
||||
remark: undefined,
|
||||
detailList: []
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
initData() {
|
||||
if (this.rowData) {
|
||||
this.form.buyerName = this.rowData.buyerName || this.rowData.partnerName;
|
||||
this.form.buyerCreditCode = this.rowData.buyerCreditCode ;
|
||||
this.form.buyerBank = this.rowData.buyerBank ;
|
||||
this.form.buyerBankAccount = this.rowData.buyerBankAccount ;
|
||||
this.form.sellerName = this.rowData.sellerName || "紫光汇智信息技术有限公司";
|
||||
this.form.sellerCreditCode = this.rowData.sellerCreditCode || "91500108MA6078GXXQ";
|
||||
this.form.sellerBank = this.rowData.sellerBank ;
|
||||
this.form.sellerBankAccount = this.rowData.sellerBankAccount;
|
||||
this.form.invoiceBillCode = this.rowData.invoiceBillCode;
|
||||
|
||||
if (this.rowData.invoiceBillCode) {
|
||||
getInvoiceProducts(this.rowData.invoiceBillCode).then(response => {
|
||||
if (response.data && response.data.length > 0) {
|
||||
this.form.detailList = response.data.map(item => {
|
||||
const row = {
|
||||
projectName: item.projectName,
|
||||
productModel: item.productModel, // Mapping projectCode to productModel as requested
|
||||
quantity: item.quantity,
|
||||
unitPrice: item.price, // Mapping price to unitPrice
|
||||
taxRate: item.taxRate,
|
||||
amount: '',
|
||||
taxAmount: ''
|
||||
};
|
||||
// Calculate initial amounts
|
||||
this.calculateAmount(row);
|
||||
return row;
|
||||
});
|
||||
} else {
|
||||
this.addDetailRow(); // Default empty row if no data
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.addDetailRow();
|
||||
}
|
||||
}
|
||||
},
|
||||
handleClose() {
|
||||
this.$emit("update:visible", false);
|
||||
},
|
||||
addDetailRow() {
|
||||
this.form.detailList.push({
|
||||
projectName: '',
|
||||
productModel: '',
|
||||
unit: '',
|
||||
unitPrice: '',
|
||||
quantity: '',
|
||||
amount: '',
|
||||
taxRate: '13',
|
||||
taxAmount: ''
|
||||
});
|
||||
},
|
||||
removeDetailRow(index) {
|
||||
this.form.detailList.splice(index, 1);
|
||||
},
|
||||
calculateAmount(row) {
|
||||
if (row.unitPrice && row.quantity) {
|
||||
row.amount = this.$calc.mul(row.unitPrice, row.quantity);
|
||||
this.calculateTax(row);
|
||||
}
|
||||
},
|
||||
calculateTax(row) {
|
||||
if (row.amount && row.taxRate != null) {
|
||||
row.taxAmount = this.$calc.mul(row.amount, this.$calc.div(row.taxRate, 100));
|
||||
}
|
||||
},
|
||||
getSummaries(param) {
|
||||
const {columns, data} = param;
|
||||
const sums = [];
|
||||
columns.forEach((column, index) => {
|
||||
if (index === 0) {
|
||||
sums[index] = '合计';
|
||||
return;
|
||||
}
|
||||
if (column.property === 'amount' || column.property === 'taxAmount') {
|
||||
const values = data.map(item => Number(item[column.property]));
|
||||
if (!values.every(value => isNaN(value))) {
|
||||
sums[index] = values.reduce((prev, curr) => {
|
||||
const value = Number(curr);
|
||||
if (!isNaN(value)) {
|
||||
return prev + curr;
|
||||
} else {
|
||||
return prev;
|
||||
}
|
||||
}, 0);
|
||||
sums[index] = sums[index].toFixed(2);
|
||||
} else {
|
||||
sums[index] = '';
|
||||
}
|
||||
} else {
|
||||
sums[index] = '';
|
||||
}
|
||||
});
|
||||
return sums;
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.loading = true;
|
||||
applyInvoice(this.form).then(response => {
|
||||
this.$modal.msgSuccess("申请提交成功");
|
||||
this.loading = false;
|
||||
this.$emit("update:visible", false);
|
||||
this.$emit("submit", this.form);
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
convertCurrency(money) {
|
||||
// 简单的数字转中文大写实现
|
||||
const cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
|
||||
const cnIntRadice = ['', '拾', '佰', '仟'];
|
||||
const cnIntUnits = ['', '万', '亿', '兆'];
|
||||
const cnDecUnits = ['角', '分', '毫', '厘'];
|
||||
const cnInteger = '整';
|
||||
const cnIntLast = '元';
|
||||
|
||||
let integerNum;
|
||||
let decimalNum;
|
||||
let chineseStr = '';
|
||||
let parts;
|
||||
|
||||
if (money === '') {
|
||||
return '';
|
||||
}
|
||||
money = parseFloat(money);
|
||||
if (money >= 999999999999) {
|
||||
return '';
|
||||
}
|
||||
if (money === 0) {
|
||||
chineseStr = cnNums[0] + cnIntLast + cnInteger;
|
||||
return chineseStr;
|
||||
}
|
||||
|
||||
money = money.toString();
|
||||
if (money.indexOf('.') === -1) {
|
||||
integerNum = money;
|
||||
decimalNum = '';
|
||||
} else {
|
||||
parts = money.split('.');
|
||||
integerNum = parts[0];
|
||||
decimalNum = parts[1].substr(0, 4);
|
||||
}
|
||||
|
||||
if (parseInt(integerNum, 10) > 0) {
|
||||
let zeroCount = 0;
|
||||
let IntLen = integerNum.length;
|
||||
for (let i = 0; i < IntLen; i++) {
|
||||
let n = integerNum.substr(i, 1);
|
||||
let p = IntLen - i - 1;
|
||||
let q = p / 4;
|
||||
let m = p % 4;
|
||||
if (n === '0') {
|
||||
zeroCount++;
|
||||
} else {
|
||||
if (zeroCount > 0) {
|
||||
chineseStr += cnNums[0];
|
||||
}
|
||||
zeroCount = 0;
|
||||
chineseStr += cnNums[parseInt(n)] + cnIntRadice[m];
|
||||
}
|
||||
if (m === 0 && zeroCount < 4) {
|
||||
chineseStr += cnIntUnits[q];
|
||||
}
|
||||
}
|
||||
chineseStr += cnIntLast;
|
||||
}
|
||||
|
||||
if (decimalNum !== '') {
|
||||
let decLen = decimalNum.length;
|
||||
for (let i = 0; i < decLen; i++) {
|
||||
let n = decimalNum.substr(i, 1);
|
||||
if (n !== '0') {
|
||||
chineseStr += cnNums[Number(n)] + cnDecUnits[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chineseStr === '') {
|
||||
chineseStr += cnNums[0] + cnIntLast + cnInteger;
|
||||
} else if (decimalNum === '') {
|
||||
chineseStr += cnInteger;
|
||||
}
|
||||
return chineseStr;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.invoice-dialog ::v-deep .el-dialog__body {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.invoice-header {
|
||||
position: relative;
|
||||
height: 80px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.header-center {
|
||||
text-align: center;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.invoice-title {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #8B4513;
|
||||
line-height: 40px;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.invoice-type-wrapper {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.invoice-type-select {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
/* Hide select border to blend in */
|
||||
.invoice-type-select ::v-deep .el-input__inner {
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
color: #8B4513;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.invoice-type-select ::v-deep .el-select__caret {
|
||||
color: #8B4513;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.header-decoration-line {
|
||||
height: 2px;
|
||||
background-color: #8B4513;
|
||||
width: 380px;
|
||||
margin: 0 auto;
|
||||
border-bottom: 1px solid #8B4513; /* 双线效果 */
|
||||
box-shadow: 0 2px 0 0 #fff, 0 4px 0 0 #8B4513;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.meta-row {
|
||||
font-size: 13px;
|
||||
color: #8B4513;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.meta-label {
|
||||
display: inline-block;
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
.invoice-body-border {
|
||||
border: 2px solid #8B4513;
|
||||
padding: 0;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.info-container {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #8B4513;
|
||||
}
|
||||
|
||||
.info-column {
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.left-column {
|
||||
border-right: 1px solid #8B4513;
|
||||
}
|
||||
|
||||
.column-label {
|
||||
width: 30px;
|
||||
padding: 0 5px;
|
||||
color: #8B4513;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
line-height: 1.4;
|
||||
border-right: 1px solid #8B4513;
|
||||
margin-right: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.column-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.condensed-item {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.condensed-item ::v-deep .el-form-item__label {
|
||||
color: #8B4513;
|
||||
font-size: 13px;
|
||||
padding-right: 8px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
/* Fix for multiline label */
|
||||
.label-wrap ::v-deep .el-form-item__label {
|
||||
line-height: 16px;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.condensed-item ::v-deep .el-input__inner {
|
||||
border-color: #dcdfe6;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
/* Table Styling */
|
||||
.items-table-container {
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #8B4513;
|
||||
}
|
||||
|
||||
.invoice-table ::v-deep th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.invoice-table ::v-deep .el-table__footer-wrapper tbody td,
|
||||
.invoice-table ::v-deep .el-table__header-wrapper tbody td {
|
||||
background-color: #fff;
|
||||
color: #8B4513;
|
||||
border-color: #8B4513;
|
||||
}
|
||||
|
||||
.invoice-table ::v-deep td, .invoice-table ::v-deep th.is-leaf {
|
||||
border-bottom: 1px solid #8B4513;
|
||||
border-right: 1px solid #8B4513;
|
||||
}
|
||||
|
||||
.invoice-table ::v-deep .el-table--border, .invoice-table ::v-deep .el-table--group {
|
||||
border-color: #8B4513;
|
||||
}
|
||||
|
||||
.no-border-input ::v-deep .el-input__inner {
|
||||
border: none;
|
||||
text-align: center;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.table-icon {
|
||||
cursor: pointer;
|
||||
color: #8B4513;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.total-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #8B4513;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
color: #8B4513;
|
||||
}
|
||||
|
||||
.total-label {
|
||||
width: 120px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.total-value-chinese {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.currency-symbol {
|
||||
border: 1px solid #8B4513;
|
||||
border-radius: 50%;
|
||||
padding: 1px 4px;
|
||||
font-size: 12px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.total-label-small {
|
||||
width: 60px;
|
||||
text-align: right;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.total-value-number {
|
||||
width: 150px;
|
||||
padding-left: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.remark-row {
|
||||
display: flex;
|
||||
min-height: 60px;
|
||||
padding: 0 10px;
|
||||
color: #8B4513;
|
||||
}
|
||||
|
||||
.remark-label {
|
||||
width: 120px;
|
||||
padding-top: 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.remark-content {
|
||||
flex: 1;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.no-border-textarea ::v-deep .el-textarea__inner {
|
||||
border: none;
|
||||
resize: none;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -8,52 +8,114 @@
|
|||
>
|
||||
<div class="dialog-body" v-if="detail">
|
||||
<div class="section">
|
||||
<el-divider content-position="left">销售-收票单</el-divider>
|
||||
<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>
|
||||
<div class="detail-item">销售-开票单编号: {{ detail.invoiceBillCode }}</div>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<div class="detail-item">客户开票时间: {{ detail.customerInvoiceTime }}</div>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">销售-生成时间: {{ detail.createTime }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">进货商名称: {{ detail.partnerName }}</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">客户名称: {{ detail.customerName }}</div>
|
||||
<div class="detail-item">含税总价(元): {{ detail.totalPriceWithTax }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">含税总价: {{ detail.invoicePriceWithTax }}</div>
|
||||
<div class="detail-item">未税总价(元): {{ detail.totalPriceWithoutTax }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">未税总价: {{ detail.invoicePriceWithoutTax }}</div>
|
||||
<div class="detail-item">税额(元): {{ $calc.sub(detail.totalPriceWithTax,detail.totalPriceWithoutTax) }}</div>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">税额: {{ detail.taxAmount }}</div>
|
||||
<div class="detail-item">发票含税总价(元): {{ detail.invoicePriceWithTax }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">收票状态:
|
||||
<dict-tag :options="dict.type.invoice_status" :value="detail.invoiceStatus"/>
|
||||
</div>
|
||||
<div class="detail-item">发票未税总价(元): {{ detail.invoicePriceWithoutTax }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">备注: {{ detail.remark }}</div>
|
||||
<div class="detail-item">发票税额(元): {{ $calc.sub(detail.invoicePriceWithTax,detail.invoicePriceWithoutTax) }}</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">票据类型:
|
||||
<span class="item-value"><dict-tag :options="dict.type.finance_invoice_type" :value="detail.invoiceType"/></span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">发票/红冲:
|
||||
{{detail.totalPriceWithTax<0?'红冲票据':'正常票据'}}
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">购买方信息_名称: {{ detail.buyerName }}</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">购买方信息_统一社会信用代码/纳税人识别号: {{ detail.buyerCreditCode }}</div>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">购买方信息_购方开户银行: {{ detail.buyerBank }}</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">购买方信息_银行账号: {{ detail.buyerBankAccount }}</div>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">销售方信息_名称: {{ detail.sellerName }}</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">销售方信息_统一社会信用代码/纳税人识别号: {{ detail.sellerCreditCode }}</div>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">销售方信息_销方开户银行: {{ detail.sellerBank }}</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">销售方信息_银行账号: {{ detail.sellerBankAccount }}</div>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">备注: {{ detail.remark }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">上传人姓名: {{ detail.createByName }}</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">开票状态:
|
||||
<dict-tag :options="dict.type.invoice_bill_status" :value="detail.invoiceStatus"/>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">审批节点: {{ detail.approveNode|| '-' }}</div>
|
||||
<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>
|
||||
<dict-tag :options="dict.type.approve_status" :value="detail.approveStatus"/></div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="detail-item">审批通过时间: {{ detail.approveTime || '-'}}</div>
|
||||
<div class="detail-item">审批通过时间 :{{detail.approveTime}}
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
|
@ -88,7 +150,7 @@ export default {
|
|||
default: () => null,
|
||||
},
|
||||
},
|
||||
dicts:['invoice_bill_type','approve_status','invoice_status'],
|
||||
dicts:['finance_invoice_type','approve_status','invoice_bill_status'],
|
||||
methods: {
|
||||
handleClose() {
|
||||
this.$emit("update:visible", false);
|
||||
|
|
|
|||
|
|
@ -121,33 +121,44 @@
|
|||
</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">
|
||||
<el-table-column label="销售-开票单编号" align="center" prop="invoiceBillCode" width="200"/>
|
||||
<el-table-column label="预计开票时间" align="center" prop="invoiceTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.customerInvoiceTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
<span>{{ parseTime(scope.row.invoiceTime, '{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" >
|
||||
<el-table-column label="进货商名称" align="center" prop="partnerName" width="300" />
|
||||
<el-table-column label="含税总价" align="center" prop="totalPriceWithTax" width="180" />
|
||||
<el-table-column label="未税总价" align="center" prop="totalPriceWithoutTax" width="180"/>
|
||||
<el-table-column label="税额" align="center" prop="taxAmount" width="180">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.invoice_status" :value="scope.row.invoiceStatus"/>
|
||||
<span>{{ $calc.sub(scope.row.totalPriceWithTax, scope.row.totalPriceWithoutTax) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批状态" align="center" prop="approveStatus" >
|
||||
<el-table-column label="发票未税总价" align="center" prop="invoicePriceWithoutTax" width="180"/>
|
||||
<el-table-column label="发票税额" align="center" prop="invoicePriceTax" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ $calc.sub(scope.row.totalPriceWithTax, scope.row.invoicePriceWithoutTax) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开票状态" align="center" prop="invoiceStatus" width="150" >
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.invoice_bill_status" :value="scope.row.invoiceStatus"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审批状态" align="center" prop="approveStatus" width="150" >
|
||||
<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">
|
||||
|
||||
<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">
|
||||
<el-table-column label="审批节点" align="center" prop="approveNode" width="200" fixed="right"/>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
|
|
@ -161,6 +172,12 @@
|
|||
icon="el-icon-document"
|
||||
@click="handleReceipt(scope.row)"
|
||||
>发票</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-s-ticket"
|
||||
@click="handleApplyInvoice(scope.row)"
|
||||
>申请开票</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
|
|
@ -193,6 +210,8 @@
|
|||
<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>
|
||||
<!-- 申请开票弹窗 -->
|
||||
<apply-invoice :visible.sync="applyOpen" :row-data="currentRow" @submit="getList"></apply-invoice>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -203,15 +222,17 @@ import { addDateRange } from "@/utils/ruoyi";
|
|||
import DetailDrawer from "./components/DetailDrawer.vue";
|
||||
import AddForm from "./components/AddForm.vue";
|
||||
import InvoiceDialog from "./components/InvoiceDialog.vue";
|
||||
import ApplyInvoice from "./components/ApplyInvoice.vue";
|
||||
|
||||
export default {
|
||||
name: "Invoice",
|
||||
components: {
|
||||
DetailDrawer,
|
||||
AddForm,
|
||||
InvoiceDialog
|
||||
InvoiceDialog,
|
||||
ApplyInvoice
|
||||
},
|
||||
dicts:['invoice_bill_type','approve_status','invoice_status'],
|
||||
dicts:['invoice_bill_type','approve_status','invoice_bill_status'],
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
|
|
@ -245,6 +266,8 @@ export default {
|
|||
detailData: null,
|
||||
// 新增弹窗
|
||||
addOpen: false,
|
||||
// 申请开票弹窗
|
||||
applyOpen: false,
|
||||
// 收票附件弹窗
|
||||
receiptOpen: false,
|
||||
currentRow: {}
|
||||
|
|
@ -309,6 +332,11 @@ export default {
|
|||
this.currentRow = row;
|
||||
this.receiptOpen = true;
|
||||
},
|
||||
/** 申请开票按钮操作 */
|
||||
handleApplyInvoice(row) {
|
||||
this.currentRow = row;
|
||||
this.applyOpen = true;
|
||||
},
|
||||
/** 红冲按钮操作 */
|
||||
handleRedRush(row) {
|
||||
this.$modal.confirm('是否确认收票单编号为"' + row.invoiceBillCode + '"的数据项进行红冲,并提交财务审批?').then(function() {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const CompressionPlugin = require('compression-webpack-plugin')
|
|||
|
||||
const name = process.env.VUE_APP_TITLE || 'UNISSENSE-OMS' // 网页标题
|
||||
|
||||
const baseUrl = 'http://localhost:28081' // 后端接口
|
||||
const baseUrl = 'http://localhost:28080' // 后端接口
|
||||
|
||||
const port = process.env.port || process.env.npm_config_port || 80 // 端口
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,12 @@ public class OmsInvoiceBillController extends BaseController
|
|||
{
|
||||
return AjaxResult.success(omsInvoiceBillService.selectOmsInvoiceBillById(id));
|
||||
}
|
||||
@RequiresPermissions("sip:invoiceBill:query")
|
||||
@PostMapping(value = "/apply")
|
||||
public AjaxResult getInfo(@RequestBody OmsInvoiceBill omsInvoiceBill)
|
||||
{
|
||||
return omsInvoiceBillService.applyInvoice(omsInvoiceBill);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增销售开票单
|
||||
|
|
@ -200,4 +206,10 @@ public class OmsInvoiceBillController extends BaseController
|
|||
return AjaxResult.error("操作失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/product/{code}")
|
||||
@ResponseBody
|
||||
public AjaxResult listProduct(@PathVariable("code") String code) {
|
||||
return AjaxResult.success(omsInvoiceBillService.listProduct(code));
|
||||
}
|
||||
}
|
||||
|
|
@ -44,6 +44,7 @@ public class InventoryOuter extends BaseEntity
|
|||
private String orderId;
|
||||
@Excel(name = "项目名称")
|
||||
private String projectName;
|
||||
private Long projectId;
|
||||
/** 产品BOM编码 */
|
||||
@Excel(name = "产品编码")
|
||||
private String productCode;
|
||||
|
|
|
|||
|
|
@ -108,6 +108,14 @@ public class OmsInvoiceBill extends BaseEntity
|
|||
private String todoId;
|
||||
private String taskId;
|
||||
|
||||
private String buyerName;
|
||||
private String buyerCreditCode;
|
||||
private String buyerBank;
|
||||
private String buyerBankAccount;
|
||||
private String sellerName;
|
||||
private String sellerCreditCode;
|
||||
private String sellerBank;
|
||||
private String sellerBankAccount;
|
||||
public BigDecimal getTaxAmount() {
|
||||
if (null != totalPriceWithTax && null != totalPriceWithoutTax){
|
||||
return totalPriceWithTax.subtract(totalPriceWithoutTax);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package com.ruoyi.sip.domain.dto;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author : ch
|
||||
* @version : 1.0
|
||||
* @ClassName : InvoiceProductDto
|
||||
* @Description :
|
||||
* @DATE : Created in 19:45 2025/12/22
|
||||
* <pre> Copyright: Copyright(c) 2025 </pre>
|
||||
* <pre> Company : 紫光汇智信息技术有限公司 </pre>
|
||||
* Modification History:
|
||||
* Date Author Version Discription
|
||||
* --------------------------------------------------------------------------
|
||||
* 2025/12/22 ch 1.0 Why & What is modified: <修改原因描述> *
|
||||
*/
|
||||
@Data
|
||||
public class InvoiceProductDto {
|
||||
private String projectName;
|
||||
private Long projectId;
|
||||
private String productName;
|
||||
private String productCode;
|
||||
private String productModel;
|
||||
private String productDesc;
|
||||
private Long quantity;
|
||||
private BigDecimal price;
|
||||
private BigDecimal taxRate;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -69,4 +69,6 @@ public interface InventoryOuterMapper
|
|||
String selectVendorById(Long id);
|
||||
|
||||
BigDecimal selectOutPriceByCode(String outerCode);
|
||||
|
||||
List<InventoryOuter> listByInvoiceBillCode(String invoiceBillCode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,4 +88,6 @@ public interface OmsInvoiceBillMapper
|
|||
List<OmsInvoiceBill> listApprove(@Param("entity") OmsInvoiceBill omsInvoiceBill, @Param("tableName") String tableName);
|
||||
|
||||
void clearRelationReceivable(String invoiceBillCode);
|
||||
|
||||
void applyInvoice(OmsInvoiceBill omsInvoiceBill);
|
||||
}
|
||||
|
|
@ -66,4 +66,5 @@ public interface IInventoryOuterService
|
|||
OuterDeliveryVo selectBaseInfoById(Long id);
|
||||
|
||||
OuterViewVo viewVo(Long id);
|
||||
List<InventoryOuter> listByInvoiceBillCode(String invoiceBillCode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package com.ruoyi.sip.service;
|
|||
|
||||
import java.util.List;
|
||||
import com.ruoyi.sip.domain.OmsInvoiceBill;
|
||||
import com.ruoyi.sip.domain.ProjectProductInfo;
|
||||
import com.ruoyi.sip.domain.dto.InvoiceProductDto;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
|
|
@ -110,4 +112,8 @@ public interface IOmsInvoiceBillService
|
|||
* @return 结果
|
||||
*/
|
||||
public AjaxResult returnInvoice(Long id);
|
||||
|
||||
List<InvoiceProductDto> listProduct(String code);
|
||||
|
||||
AjaxResult applyInvoice(OmsInvoiceBill omsInvoiceBill);
|
||||
}
|
||||
|
|
@ -318,4 +318,9 @@ public class InventoryOuterServiceImpl implements IInventoryOuterService
|
|||
return outerViewVo;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InventoryOuter> listByInvoiceBillCode(String invoiceBillCode) {
|
||||
return inventoryOuterMapper.listByInvoiceBillCode(invoiceBillCode);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package com.ruoyi.sip.service.impl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
|
|
@ -15,13 +15,11 @@ 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.*;
|
||||
import com.ruoyi.sip.domain.dto.InvoiceProductDto;
|
||||
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 com.ruoyi.sip.service.*;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -29,8 +27,6 @@ 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;
|
||||
|
||||
|
|
@ -61,6 +57,11 @@ public class OmsInvoiceBillServiceImpl implements IOmsInvoiceBillService, TodoCo
|
|||
@Autowired
|
||||
private IOmsReceivableInvoiceDetailService detailService;
|
||||
|
||||
@Autowired
|
||||
private IInventoryOuterService outerService;
|
||||
@Autowired
|
||||
private IProjectProductInfoService productInfoService;
|
||||
|
||||
/**
|
||||
* 查询销售开票单
|
||||
*
|
||||
|
|
@ -319,6 +320,53 @@ public class OmsInvoiceBillServiceImpl implements IOmsInvoiceBillService, TodoCo
|
|||
return AjaxResult.success("退回开票单成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InvoiceProductDto> listProduct(String code) {
|
||||
List<InventoryOuter> inventoryOuters = outerService.listByInvoiceBillCode(code);
|
||||
if (CollUtil.isEmpty(inventoryOuters)){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<String> orderCodeList = inventoryOuters.stream().map(InventoryOuter::getOrderCode).collect(Collectors.toList());
|
||||
List<ProjectProductInfo> projectProductInfos = productInfoService.selectProjectProductInfoListByOrderCode(orderCodeList);
|
||||
if (CollUtil.isEmpty(projectProductInfos)){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Map<Long, Map<String, ProjectProductInfo>> priceMap = projectProductInfos.stream().collect(Collectors.groupingBy(ProjectProductInfo::getProjectId,
|
||||
Collectors.toMap(ProjectProductInfo::getProductBomCode, Function.identity() , (v1, v2) -> v1))
|
||||
);
|
||||
|
||||
return inventoryOuters.stream().map(inventoryOuter -> {
|
||||
InvoiceProductDto invoiceProductDto = new InvoiceProductDto();
|
||||
invoiceProductDto.setProductCode(inventoryOuter.getProductCode());
|
||||
invoiceProductDto.setQuantity(inventoryOuter.getQuantity());
|
||||
invoiceProductDto.setProjectName(inventoryOuter.getProjectName());
|
||||
invoiceProductDto.setProjectId(inventoryOuter.getProjectId());
|
||||
Map<String, ProjectProductInfo> productInfoMap = priceMap.get(inventoryOuter.getProjectId());
|
||||
if (CollUtil.isNotEmpty(productInfoMap)){
|
||||
ProjectProductInfo productInfo = productInfoMap.get(inventoryOuter.getProductCode());
|
||||
if (productInfo != null){
|
||||
invoiceProductDto.setProductModel(productInfo.getModel());
|
||||
invoiceProductDto.setProductName(productInfo.getProductName());
|
||||
invoiceProductDto.setProductDesc(productInfo.getProductDesc());
|
||||
invoiceProductDto.setPrice(productInfo.getPrice().divide(
|
||||
BigDecimal.ONE.add(productInfo.getTaxRate().divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP))
|
||||
, 2, RoundingMode.HALF_UP));
|
||||
invoiceProductDto.setTaxRate(productInfo.getTaxRate());
|
||||
}
|
||||
}
|
||||
return invoiceProductDto;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult applyInvoice(OmsInvoiceBill omsInvoiceBill) {
|
||||
// todo 保存detailList
|
||||
//todo 开启审批流程
|
||||
omsInvoiceBill.setApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode());
|
||||
omsInvoiceBillMapper.applyInvoice(omsInvoiceBill);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object todoDetail(String businessKey, String processKey, String todoId) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
t1.delivery_status,
|
||||
t2.model,
|
||||
t3.id as order_id,
|
||||
t3.project_id,
|
||||
t5.user_name as createByName,
|
||||
t4.project_code,
|
||||
t4.project_name
|
||||
|
|
@ -164,6 +165,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
where t2.outer_code = #{outerCode}
|
||||
|
||||
</select>
|
||||
<select id="listByInvoiceBillCode" resultType="com.ruoyi.sip.domain.InventoryOuter">
|
||||
<include refid="selectInventoryOuterRelationVo"/>
|
||||
JOIN oms_receivable_bill b
|
||||
ON t1.outer_code = b.inventory_code
|
||||
JOIN oms_receivable_invoice_detail d
|
||||
ON d.receivable_bill_id = b.id
|
||||
WHERE d.invoice_bill_code =#{code};
|
||||
</select>
|
||||
|
||||
<insert id="insertInventoryOuter" parameterType="InventoryOuter" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into oms_inventory_outer
|
||||
|
|
|
|||
|
|
@ -28,21 +28,30 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<result property="approveTime" column="approve_time" />
|
||||
<result property="refundStatus" column="refund_status" />
|
||||
<result property="originalBillId" column="original_bill_id" />
|
||||
<result property="buyerName" column="buyer_name" />
|
||||
<result property="buyerCreditCode" column="buyer_credit_code" />
|
||||
<result property="buyerBank" column="buyer_bank" />
|
||||
<result property="buyerBankAccount" column="buyer_bank_account" />
|
||||
<result property="sellerName" column="seller_name" />
|
||||
<result property="sellerCreditCode" column="seller_credit_code" />
|
||||
<result property="sellerBank" column="seller_bank" />
|
||||
<result property="sellerBankAccount" column="seller_bank_account" />
|
||||
</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,
|
||||
invoice_time, partner_code,partner_name, 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
|
||||
, original_bill_id, buyer_name, buyer_credit_code, buyer_bank, buyer_bank_account,
|
||||
seller_name, seller_credit_code, seller_bank, seller_bank_account
|
||||
from oms_invoice_bill
|
||||
</sql>
|
||||
|
||||
<select id="selectOmsInvoiceBillList" parameterType="com.ruoyi.sip.domain.OmsInvoiceBill" resultMap="OmsInvoiceBillResult">
|
||||
<include refid="selectOmsInvoiceBillVo"/>
|
||||
<where>
|
||||
<where>
|
||||
<if test="invoiceBillCode != null and invoiceBillCode != ''">
|
||||
and invoice_bill_code = #{invoiceBillCode}
|
||||
</if>
|
||||
|
|
@ -107,6 +116,30 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="originalBillId != null ">
|
||||
and original_bill_id = #{originalBillId}
|
||||
</if>
|
||||
<if test="buyerName != null and buyerName != ''">
|
||||
and buyer_name = #{buyerName}
|
||||
</if>
|
||||
<if test="buyerCreditCode != null and buyerCreditCode != ''">
|
||||
and buyer_credit_code = #{buyerCreditCode}
|
||||
</if>
|
||||
<if test="buyerBank != null and buyerBank != ''">
|
||||
and buyer_bank = #{buyerBank}
|
||||
</if>
|
||||
<if test="buyerBankAccount != null and buyerBankAccount != ''">
|
||||
and buyer_bank_account = #{buyerBankAccount}
|
||||
</if>
|
||||
<if test="sellerName != null and sellerName != ''">
|
||||
and seller_name = #{sellerName}
|
||||
</if>
|
||||
<if test="sellerCreditCode != null and sellerCreditCode != ''">
|
||||
and seller_credit_code = #{sellerCreditCode}
|
||||
</if>
|
||||
<if test="sellerBank != null and sellerBank != ''">
|
||||
and seller_bank = #{sellerBank}
|
||||
</if>
|
||||
<if test="sellerBankAccount != null and sellerBankAccount != ''">
|
||||
and seller_bank_account = #{sellerBankAccount}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
|
|
@ -185,6 +218,30 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="originalBillId != null">
|
||||
original_bill_id,
|
||||
</if>
|
||||
<if test="buyerName != null and buyerName != ''">
|
||||
buyer_name,
|
||||
</if>
|
||||
<if test="buyerCreditCode != null and buyerCreditCode != ''">
|
||||
buyer_credit_code,
|
||||
</if>
|
||||
<if test="buyerBank != null and buyerBank != ''">
|
||||
buyer_bank,
|
||||
</if>
|
||||
<if test="buyerBankAccount != null and buyerBankAccount != ''">
|
||||
buyer_bank_account,
|
||||
</if>
|
||||
<if test="sellerName != null and sellerName != ''">
|
||||
seller_name,
|
||||
</if>
|
||||
<if test="sellerCreditCode != null and sellerCreditCode != ''">
|
||||
seller_credit_code,
|
||||
</if>
|
||||
<if test="sellerBank != null and sellerBank != ''">
|
||||
seller_bank,
|
||||
</if>
|
||||
<if test="sellerBankAccount != null and sellerBankAccount != ''">
|
||||
seller_bank_account,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="invoiceBillCode != null and invoiceBillCode != ''">
|
||||
|
|
@ -254,6 +311,30 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="originalBillId != null">
|
||||
#{originalBillId},
|
||||
</if>
|
||||
<if test="buyerName != null and buyerName != ''">
|
||||
#{buyerName},
|
||||
</if>
|
||||
<if test="buyerCreditCode != null and buyerCreditCode != ''">
|
||||
#{buyerCreditCode},
|
||||
</if>
|
||||
<if test="buyerBank != null and buyerBank != ''">
|
||||
#{buyerBank},
|
||||
</if>
|
||||
<if test="buyerBankAccount != null and buyerBankAccount != ''">
|
||||
#{buyerBankAccount},
|
||||
</if>
|
||||
<if test="sellerName != null and sellerName != ''">
|
||||
#{sellerName},
|
||||
</if>
|
||||
<if test="sellerCreditCode != null and sellerCreditCode != ''">
|
||||
#{sellerCreditCode},
|
||||
</if>
|
||||
<if test="sellerBank != null and sellerBank != ''">
|
||||
#{sellerBank},
|
||||
</if>
|
||||
<if test="sellerBankAccount != null and sellerBankAccount != ''">
|
||||
#{sellerBankAccount},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
|
|
@ -325,6 +406,30 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="originalBillId != null">
|
||||
original_bill_id = #{originalBillId},
|
||||
</if>
|
||||
<if test="buyerName != null and buyerName != ''">
|
||||
buyer_name = #{buyerName},
|
||||
</if>
|
||||
<if test="buyerCreditCode != null and buyerCreditCode != ''">
|
||||
buyer_credit_code = #{buyerCreditCode},
|
||||
</if>
|
||||
<if test="buyerBank != null and buyerBank != ''">
|
||||
buyer_bank = #{buyerBank},
|
||||
</if>
|
||||
<if test="buyerBankAccount != null and buyerBankAccount != ''">
|
||||
buyer_bank_account = #{buyerBankAccount},
|
||||
</if>
|
||||
<if test="sellerName != null and sellerName != ''">
|
||||
seller_name = #{sellerName},
|
||||
</if>
|
||||
<if test="sellerCreditCode != null and sellerCreditCode != ''">
|
||||
seller_credit_code = #{sellerCreditCode},
|
||||
</if>
|
||||
<if test="sellerBank != null and sellerBank != ''">
|
||||
seller_bank = #{sellerBank},
|
||||
</if>
|
||||
<if test="sellerBankAccount != null and sellerBankAccount != ''">
|
||||
seller_bank_account = #{sellerBankAccount},
|
||||
</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
|
@ -353,6 +458,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
</trim>
|
||||
where invoice_bill_code = #{invoiceBillCode}
|
||||
</update>
|
||||
<update id="applyInvoice">
|
||||
update oms_invoice_bill
|
||||
set buyer_name = #{buyerName},
|
||||
buyer_credit_code = #{buyerCreditCode},
|
||||
buyer_bank = #{buyerBank},
|
||||
buyer_bank_account = #{buyerBankAccount},
|
||||
seller_name = #{sellerName},
|
||||
seller_credit_code = #{sellerCreditCode},
|
||||
seller_bank = #{sellerBank},
|
||||
seller_bank_account = #{sellerBankAccount},
|
||||
approve_status=#{approveStatus}
|
||||
where invoice_bill_code = #{invoiceBillCode}
|
||||
|
||||
</update>
|
||||
|
||||
<delete id="deleteOmsInvoiceBillById" parameterType="Long">
|
||||
delete from oms_invoice_bill where id = #{id}
|
||||
|
|
|
|||
Loading…
Reference in New Issue