fix:发货管理2608

dev_1.0.2
jiangpeng 2026-08-28 16:48:21 +08:00
parent 625519c2c2
commit 415b9b3e46
90 changed files with 3521 additions and 378 deletions

View File

@ -28,18 +28,20 @@
"axios": "0.28.1", "axios": "0.28.1",
"clipboard": "2.0.8", "clipboard": "2.0.8",
"core-js": "3.37.1", "core-js": "3.37.1",
"decimal.js": "10.4.2",
"echarts": "5.4.0", "echarts": "5.4.0",
"element-ui": "2.15.14", "element-ui": "2.15.14",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"fuse.js": "6.4.3", "fuse.js": "6.4.3",
"highlight.js": "9.18.5", "highlight.js": "9.18.5",
"html2canvas": "^1.4.1",
"js-beautify": "1.13.0", "js-beautify": "1.13.0",
"js-cookie": "3.0.1", "js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1", "jsencrypt": "3.0.0-rc.1",
"jspdf": "^2.5.1",
"jszip": "^3.10.1",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"quill": "2.0.2", "quill": "2.0.2",
"html2canvas": "^1.4.1",
"jspdf": "^2.5.1",
"screenfull": "5.0.2", "screenfull": "5.0.2",
"sortablejs": "1.10.2", "sortablejs": "1.10.2",
"splitpanes": "2.4.1", "splitpanes": "2.4.1",
@ -48,8 +50,7 @@
"vue-cropper": "0.5.5", "vue-cropper": "0.5.5",
"vue-router": "3.4.9", "vue-router": "3.4.9",
"vuedraggable": "2.24.3", "vuedraggable": "2.24.3",
"vuex": "3.6.0", "vuex": "3.6.0"
"decimal.js": "10.4.2"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "4.4.6", "@vue/cli-plugin-babel": "4.4.6",

View File

@ -18,3 +18,12 @@ export function getApprovalTaskTotal() {
method: 'get' method: 'get'
}) })
} }
// 新增流程确认记录
export function addTodoConfirm(data) {
return request({
url: '/approve/task/vue/confirm',
method: 'post',
data
})
}

View File

@ -9,3 +9,13 @@ export function listReport(query) {
data: query data: query
}) })
} }
// 查询供货商维度报表列表
export function listSupplierReport(query) {
return request({
url: '/finance/report/listSupplier',
method: 'post',
headers: { 'Content-Type': 'multipart/form-data' },
data: query
})
}

View File

@ -17,6 +17,14 @@ export function listCompletedFlows(data) {
data: data data: data
}) })
} }
// 按业务单号查询待办记录(查看申请详情用)
export function listApplyFlows(data) {
return request({
url: '/flow/todo/apply-list',
method: 'post',
data: data
})
}
// 通用审批 // 通用审批
export function approveTask(data) { export function approveTask(data) {
return request({ return request({

View File

@ -52,6 +52,15 @@ export function recallDelivery(id) {
}) })
} }
// 提交出库撤回审批(跨天发货记录)
export function recallApply(id, reason, amountChanged) {
return request({
url: '/inventory/delivery/vue/recall/apply',
method: 'post',
data: {id, reason, amountChanged}
})
}
// 导出采购合同 // 导出采购合同
export function exportDelivery(query) { export function exportDelivery(query) {
return request({ return request({

View File

@ -70,6 +70,15 @@ export function recallExecution(id) {
params: { id } params: { id }
}) })
} }
// 提交撤单审批申请
export function recallExecutionApply(id, reason, amountChanged) {
return request({
url: '/inventory/execution/vue/recall/apply',
method: 'post',
data: { id, reason, amountChanged }
})
}
export function exportExecution(data) { export function exportExecution(data) {
return request({ return request({
url: `/inventory/execution/vue/export`, url: `/inventory/execution/vue/export`,

View File

@ -104,6 +104,18 @@
margin-left: 1px; margin-left: 1px;
} }
} }
// + 穿
.el-table__fixed,
.el-table__fixed-right {
background-color: #fff;
z-index: 3;
}
.el-table__fixed .el-table__cell,
.el-table__fixed-right .el-table__cell {
background-color: #fff;
}
} }
/** 表单布局 **/ /** 表单布局 **/

View File

@ -0,0 +1,359 @@
<template>
<el-dialog
title="订单撤回审批"
:visible="dialogVisible"
:close-on-click-modal="false"
width="80%"
top="5vh"
append-to-body
@update:visible="handleVisibleChange"
>
<div v-loading="loading" style="max-height: 70vh; overflow-y: auto;">
<div class="approve-container">
<ApproveLayout ref="approveLayout" title="紫光汇智信息技术有限公司">
<template #default>
<div style="display: flex;align-items: center;justify-content: center;">
<span style="margin-left: 10px;color: black;font-size: 30px">
紫光汇智信息技术有限公司订单撤回审批
</span>
</div>
<el-form ref="orderForm" :model="order" label-width="120px" class="mb20">
<h3 class="section-title">订单信息</h3>
<order-info-display
:order-data.sync="order"
/>
</el-form>
<h3 class="section-title">配置信息</h3>
<config-info
:order-data="order"
class="mb20"
/>
</template>
<template #footer>
<p>{{ order.projectCode }}-{{ order.orderCode }}-Rev.{{ order.versionCode }}</p>
</template>
</ApproveLayout>
<!-- 撤单信息 -->
<el-form label-width="120px" class="mb20">
<h3 class="section-title">撤单信息</h3>
<el-form-item label="撤单原因:">
<el-input :value="reason" readonly type="textarea" :rows="2" />
</el-form-item>
<el-form-item label="金额是否变化:">
<el-input :value="amountChanged || '—'" readonly />
</el-form-item>
<el-row>
<el-col :span="8">
<el-form-item label="出库状态:">
<dict-tag :options="dict.type.execution_outer_status" :value="order.outerStatus"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="发货状态:">
<dict-tag :options="dict.type.execution_delivery_status" :value="order.deliveryStatus"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="签收状态:">
<dict-tag :options="dict.type.execution_sign_status" :value="order.signStatus"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 流转过程 -->
<el-tabs v-model="activeTab" class="approve-tabs">
<el-tab-pane label="流转过程" name="process">
<div class="process-container">
<el-tabs :value="activeVersionTab" @input="handleVersionTabChange" type="card" v-if="uniqueVersions.length > 0">
<el-tab-pane
v-for="version in uniqueVersions"
:key="version"
:label="'版本号Rev.' + version"
:name="version">
<el-timeline>
<el-timeline-item
v-for="log in groupedApproveLogs[version]"
:key="log.id"
:timestamp="log.approveTime"
placement="top">
<el-card>
<h4>{{ log.approveOpinion }}</h4>
<p><b>操作人:</b> {{ log.approveUserName }}</p>
<p><b>审批状态:</b> <el-tag :type="getStatusTagType(log.approveStatus)" size="small">{{ getStatusText(log.approveStatus) }}</el-tag></p>
</el-card>
</el-timeline-item>
</el-timeline>
</el-tab-pane>
</el-tabs>
<div v-else></div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
<span slot="footer" class="dialog-footer" v-if="showApprove && taskId">
<el-button @click="handleVisibleChange(false)"> </el-button>
<el-button type="danger" @click="openOpinionDialog('reject')"> </el-button>
<el-button type="primary" @click="openOpinionDialog('approve')"> </el-button>
</span>
<span slot="footer" class="dialog-footer" v-else>
<el-button @click="handleVisibleChange(false)"> </el-button>
</span>
<!-- 审批意见对话框 -->
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="500px" append-to-body :close-on-click-modal="false" :close-on-press-escape="false">
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
<el-form-item label="审批意见" prop="approveOpinion">
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见" :disabled="submitLoading"/>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="opinionDialogVisible = false" :disabled="submitLoading"> </el-button>
<el-button type="primary" @click="showConfirmDialog" :loading="submitLoading"> </el-button>
</span>
</el-dialog>
</el-dialog>
</template>
<script>
import { getOrder } from '@/api/approve/order/index'
import { listCompletedFlows, listApplyFlows, approveTask } from '@/api/flow'
import ConfigInfo from '@/views/approve/order/ConfigInfo.vue'
import ApproveLayout from '@/views/approve/ApproveLayout.vue'
import OrderInfoDisplay from '@/views/project/order/components/OrderInfoDisplay.vue'
export default {
name: 'OrderRebackDetail',
dicts: ['execution_outer_status', 'execution_delivery_status', 'execution_sign_status'],
components: {
ApproveLayout,
OrderInfoDisplay,
ConfigInfo
},
props: {
visible: {
type: Boolean,
default: false
},
// id
orderId: {
type: [Number, String],
default: null
},
// businessKey
orderCode: {
type: String,
default: ''
},
processKey: {
type: String,
default: 'order_reback'
},
// id
taskId: {
type: [Number, String],
default: null
},
//
showApprove: {
type: Boolean,
default: false
}
},
data() {
return {
dialogVisible: false,
loading: false,
order: {},
logs: [],
reason: '',
amountChanged: '',
activeTab: 'process',
activeVersionTab: null,
confirmDialogTitle: '',
opinionDialogVisible: false,
currentApproveType: null,
submitLoading: false,
opinionForm: { approveOpinion: '' },
opinionRules: {
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }]
}
}
},
computed: {
//
uniqueVersions() {
if (!this.logs || this.logs.length === 0) return []
const versions = [...new Set(this.logs.map(log => log.extendField1))].filter(v => v !== null && v !== undefined && v !== '')
return versions.sort((a, b) => b - a) //
},
//
groupedApproveLogs() {
if (!this.logs || this.logs.length === 0) return {}
return this.logs.reduce((acc, log) => {
const version = log.extendField1
if (!acc[version]) acc[version] = []
acc[version].push(log)
return acc
}, {})
}
},
watch: {
visible(val) {
this.dialogVisible = val
if (val) {
this.loadDetail()
}
}
},
methods: {
// prop
handleVisibleChange(val) {
this.dialogVisible = val
this.$emit('update:visible', val)
},
//
loadDetail() {
this.loading = true
this.order = {}
this.logs = []
this.reason = ''
this.amountChanged = ''
this.activeVersionTab = null
if (!this.orderId) {
this.loading = false
return
}
getOrder(this.orderId).then(response => {
const data = response.data || {}
this.order = data.projectOrderInfo || {}
const businessKey = this.order.orderCode || this.orderCode
this.loadFlows(businessKey)
}).catch(error => {
console.error('获取订单详情失败: ', error)
this.$modal.msgError('获取订单详情失败!')
this.loading = false
})
},
loadFlows(businessKey) {
const processKeyList = this.processKey ? [this.processKey] : ['order_reback']
listCompletedFlows({ businessKey: businessKey, processKeyList }).then(res => {
this.logs = res.data || []
// extendField2 extendField3extendField1
const applyLog = this.logs.find(log => log.extendField2)
if (applyLog) {
this.reason = applyLog.extendField2
this.amountChanged = applyLog.extendField3 || ''
} else {
//
listApplyFlows({ businessKey: businessKey, processKey: this.processKey }).then(todoRes => {
const todoList = todoRes.data || []
const apply = todoList.find(item => item.extendField2)
this.reason = apply ? apply.extendField2 : ''
this.amountChanged = apply ? (apply.extendField3 || '') : ''
}).catch(() => {})
}
if (this.uniqueVersions.length > 0) {
this.activeVersionTab = String(this.uniqueVersions[0])
}
this.loading = false
}).catch(() => {
this.logs = []
this.loading = false
})
},
openOpinionDialog(type) {
this.currentApproveType = type
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批'
this.opinionForm.approveOpinion = ''
this.opinionDialogVisible = true
this.$nextTick(() => {
this.$refs.opinionForm && this.$refs.opinionForm.clearValidate()
})
},
showConfirmDialog() {
this.$refs.opinionForm.validate(valid => {
if (valid) {
this.opinionDialogVisible = false
this.submitApproval()
}
})
},
submitApproval() {
this.submitLoading = true
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0
const params = {
businessKey: this.order.orderCode || this.orderCode,
processKey: this.processKey,
taskId: this.taskId,
variables: {
comment: this.opinionForm.approveOpinion,
approveBtn: approveBtn
}
}
approveTask(params).then(() => {
this.submitLoading = false
this.$modal.msgSuccess(this.confirmDialogTitle + '成功')
this.handleVisibleChange(false)
this.$emit('success')
}).catch(error => {
this.submitLoading = false
console.error('审批失败: ', error)
this.$modal.msgError('审批失败!' + (error.msg || error.message))
})
},
getStatusTagType(status) {
const typeMap = {
'1': 'info', //
'2': 'danger', //
'3': 'success' //
}
return typeMap[String(status)] || 'info'
},
// Tab/
handleVersionTabChange(val) {
if (val !== null && val !== undefined && val !== '' && this.uniqueVersions.includes(val)) {
this.activeVersionTab = val
}
},
getStatusText(status) {
const textMap = { '1': '提交审批', '2': '驳回', '3': '批准' }
return textMap[String(status)] || '提交审批'
}
}
}
</script>
<style scoped>
.section-title {
font-size: 16px;
font-weight: bold;
color: #303133;
margin-bottom: 15px;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
.mb20 {
margin-bottom: 20px;
}
/* Tab样式 */
.approve-tabs {
margin-top: 20px;
margin-left: 10px;
}
/* 流转过程容器 */
.process-container {
padding: 0;
}
/* 审批意见弹窗样式 */
::v-deep .el-dialog__body {
padding-top: 10px;
}
</style>

View File

@ -0,0 +1,312 @@
<template>
<el-dialog
title="出库撤回审批"
:visible="dialogVisible"
:close-on-click-modal="false"
width="80%"
top="5vh"
append-to-body
destroy-on-close
@update:visible="handleVisibleChange"
>
<div v-loading="loading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
<el-form label-width="110px">
<el-row>
<el-col :span="12">
<el-form-item label="出库单号:">
<el-input :value="form.outerCode" readonly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物流单号:">
<el-input :value="form.logisticsCode" readonly />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="物流公司:">
<el-input :value="form.logisticsCompany" readonly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="仓库:">
<el-input :value="form.warehouseName" readonly />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="发货时间:">
<el-input :value="form.deliveryTime" readonly />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发货数量:">
<el-input :value="form.quantity" readonly />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="收货地址:">
<el-input :value="form.notifierAddress" readonly />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="撤回原因:">
<el-input :value="reason" readonly type="textarea" :rows="2" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="金额是否变化:">
<el-input :value="amountChanged || '—'" readonly />
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-divider content-position="left">SN码列表</el-divider>
<el-table v-loading="snLoading" :data="snList" border size="mini">
<el-table-column type="index" label="序号" align="center" width="60" />
<el-table-column label="SN码" align="center" prop="productSn"/>
<el-table-column label="授权码" align="center" prop="licenseKey"/>
<el-table-column label="产品编码" align="center" prop="productCode"/>
<el-table-column label="产品型号" align="center" prop="model"/>
<el-table-column label="描述" align="center" prop="productDesc"/>
<el-table-column label="仓库" align="center" prop="warehouseName"/>
</el-table>
<pagination v-show="snTotal>0" :total="snTotal" :page.sync="snQueryParams.pageNum" :limit.sync="snQueryParams.pageSize" @pagination="getSnList"/>
<el-divider content-position="left">流转意见</el-divider>
<div class="process-container">
<el-timeline>
<el-timeline-item v-for="log in logs" :key="log.id" :timestamp="log.approveTime" placement="top">
<el-card>
<h4>{{ log.approveOpinion }}</h4>
<p><b>操作人:</b> {{ log.approveUserName }}</p>
<p><b>审批状态:</b>
<el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag>
</p>
</el-card>
</el-timeline-item>
</el-timeline>
<div v-if="!logs || logs.length === 0"></div>
</div>
</div>
<span slot="footer" class="dialog-footer" v-if="showApprove && taskId">
<el-button @click="handleVisibleChange(false)"> </el-button>
<el-button type="danger" @click="openOpinionDialog('reject')"> </el-button>
<el-button type="primary" @click="openOpinionDialog('approve')"> </el-button>
</span>
<span slot="footer" class="dialog-footer" v-else>
<el-button @click="handleVisibleChange(false)"> </el-button>
</span>
<!-- 审批意见对话框 -->
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
<el-form-item label="审批意见" prop="approveOpinion">
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="opinionDialogVisible = false"> </el-button>
<el-button type="primary" @click="showConfirmDialog()"> </el-button>
</span>
</el-dialog>
</el-dialog>
</template>
<script>
import { getDelivery, listProductSn } from '@/api/inventory/delivery'
import { listCompletedFlows, listApplyFlows, approveTask } from '@/api/flow'
export default {
name: 'OuterRebackDetail',
props: {
visible: {
type: Boolean,
default: false
},
// idSN
deliveryId: {
type: [Number, String],
default: null
},
//
outerCode: {
type: String,
default: ''
},
processKey: {
type: String,
default: 'outer_reback'
},
// id
taskId: {
type: [Number, String],
default: null
},
//
showApprove: {
type: Boolean,
default: false
}
},
data() {
return {
dialogVisible: false,
loading: false,
form: {},
logs: [],
reason: '',
amountChanged: '',
// SN
snLoading: false,
snList: [],
snTotal: 0,
snQueryParams: {
pageNum: 1,
pageSize: 10,
deliveryId: null,
// /SNouter_code
inventoryStatus: null,
outerCode: null,
warehouseId: null,
productSnList: []
},
confirmDialogTitle: '',
opinionDialogVisible: false,
currentApproveType: null,
opinionForm: { approveOpinion: '' },
opinionRules: {
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }]
}
}
},
watch: {
visible(val) {
this.dialogVisible = val
if (val) {
this.loadDetail()
}
}
},
methods: {
// prop
handleVisibleChange(val) {
this.dialogVisible = val
this.$emit('update:visible', val)
},
// SN
loadDetail() {
this.loading = true
this.form = {}
this.logs = []
this.reason = ''
this.amountChanged = ''
this.snList = []
this.snTotal = 0
if (!this.deliveryId) {
this.loading = false
return
}
getDelivery(this.deliveryId).then(response => {
this.form = response.data || {}
// SN outer_code
this.snQueryParams.deliveryId = this.deliveryId
this.snQueryParams.warehouseId = this.form.warehouseId
this.snQueryParams.productSnList = this.form.productSnList
this.getSnList()
const businessKey = this.form.outerCode || this.outerCode
this.loadFlows(businessKey)
}).catch(error => {
console.error('获取发货记录详情失败: ', error)
this.$modal.msgError('获取发货记录详情失败!')
this.loading = false
})
},
// SN
getSnList() {
this.snLoading = true
listProductSn(this.snQueryParams).then(res => {
this.snList = res.rows
this.snTotal = res.total
this.snLoading = false
}).catch(() => {
this.snLoading = false
})
},
loadFlows(businessKey) {
const processKeyList = this.processKey ? [this.processKey] : ['outer_reback']
listCompletedFlows({ businessKey: businessKey, processKeyList }).then(res => {
this.logs = res.data || []
// extend_field1 extend_field3
const applyLog = this.logs.find(log => log.extendField1)
if (applyLog) {
this.reason = applyLog.extendField1
this.amountChanged = applyLog.extendField3 || ''
} else {
//
listApplyFlows({ businessKey: businessKey, processKey: this.processKey }).then(todoRes => {
const todoList = todoRes.data || []
const apply = todoList.find(item => item.extendField1)
this.reason = apply ? apply.extendField1 : ''
this.amountChanged = apply ? (apply.extendField3 || '') : ''
}).catch(() => {})
}
this.loading = false
}).catch(() => {
this.logs = []
this.loading = false
})
},
openOpinionDialog(type) {
this.currentApproveType = type
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批'
this.opinionForm.approveOpinion = ''
this.opinionDialogVisible = true
this.$nextTick(() => {
this.$refs.opinionForm && this.$refs.opinionForm.clearValidate()
})
},
showConfirmDialog() {
this.$refs.opinionForm.validate(valid => {
if (valid) {
this.opinionDialogVisible = false
this.submitApproval()
}
})
},
submitApproval() {
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0
const params = {
businessKey: this.form.outerCode || this.outerCode,
processKey: this.processKey,
taskId: this.taskId,
variables: {
comment: this.opinionForm.approveOpinion,
approveBtn: approveBtn
}
}
approveTask(params).then(() => {
this.$modal.msgSuccess(this.confirmDialogTitle + '成功')
this.handleVisibleChange(false)
this.$emit('success')
}).catch(error => {
console.error('审批失败: ', error)
this.$modal.msgError('审批失败!' + (error.msg || error.message))
})
},
getStatusText(status) {
const textMap = { '1': '提交审批', '2': '驳回', '3': '批准' }
return textMap[String(status)] || '提交审批'
}
}
}
</script>

View File

@ -75,7 +75,7 @@
<el-table-column label="流程编号" prop="processNo" min-width="195" /> <el-table-column label="流程编号" prop="processNo" min-width="195" />
<el-table-column label="流程标题" prop="processTitle" min-width="250"> <el-table-column label="流程标题" prop="processTitle" min-width="250">
<template slot-scope="scope"> <template slot-scope="scope">
<span v-if="isApproveButton(scope.row)" class="urgent-dot"></span> <span v-if="isApproveButton(scope.row) && !scope.row._confirmed" class="urgent-dot"></span>
<span>{{ scope.row.processTitle }}</span> <span>{{ scope.row.processTitle }}</span>
</template> </template>
</el-table-column> </el-table-column>
@ -84,14 +84,20 @@
{{ getApproveTypeLabel(scope.row.approveType) }} {{ getApproveTypeLabel(scope.row.approveType) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="发起人" prop="initiator" min-width="110" /> <el-table-column label="发起人" prop="initiator" min-width="80" />
<el-table-column label="发起时间" prop="startTime" min-width="135" sortable="custom" :sort-orders="['descending', 'ascending']" /> <el-table-column label="发起时间" prop="startTime" min-width="150" sortable="custom" :sort-orders="['descending', 'ascending']" />
<el-table-column label="含税总计(元)" prop="totalAmount" min-width="145"> <el-table-column label="含税总计(元)" prop="totalAmount" min-width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<span class="amount">{{ formatAmount(scope.row.totalAmount) }}</span> <span class="amount">{{ formatAmount(scope.row.totalAmount) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="90" align="center"> <el-table-column label="审批状态" prop="approveStatus" min-width="90" align="center">
<template slot-scope="scope">
<el-tag :type="getApproveStatusTagType(scope.row)">{{ getApproveStatusLabel(scope.row) }}</el-tag>
</template>
</el-table-column>
<el-table-column label="审批人" prop="approveUserNames" min-width="160" />
<el-table-column label="操作" width="80" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
type="text" type="text"
@ -133,6 +139,9 @@
<el-button type="danger" @click="handleReject"> </el-button> <el-button type="danger" @click="handleReject"> </el-button>
<el-button type="primary" @click="handleApproveConfirm"> </el-button> <el-button type="primary" @click="handleApproveConfirm"> </el-button>
</span> </span>
<span slot="footer" class="dialog-footer" v-else>
<el-button @click="orderDrawerVisible = false"> </el-button>
</span>
</el-dialog> </el-dialog>
<!-- 采购单审批详情弹窗 --> <!-- 采购单审批详情弹窗 -->
@ -468,11 +477,32 @@
<el-button type="primary" @click="showInvoiceConfirmDialog()"> </el-button> <el-button type="primary" @click="showInvoiceConfirmDialog()"> </el-button>
</span> </span>
</el-dialog> </el-dialog>
<!-- 出库撤回审批详情独立组件 -->
<outer-reback-detail
:visible.sync="outerRebackDialogVisible"
:delivery-id="outerRebackDeliveryId"
:outer-code="outerRebackOuterCode"
:process-key="outerRebackProcessKey"
:task-id="outerRebackTaskId"
:show-approve="outerRebackShowApproveButtons"
@success="handleOuterRebackApproved"
/>
<!-- 撤单审批详情独立组件 -->
<order-reback-detail
:visible.sync="orderRebackDialogVisible"
:order-id="orderRebackOrderId"
:order-code="orderRebackOrderCode"
:process-key="orderRebackProcessKey"
:task-id="orderRebackTaskId"
:show-approve="orderRebackShowApproveButtons"
@success="handleOrderRebackApproved"
/>
</div> </div>
</template> </template>
<script> <script>
import { listApprovalTask, getApprovalTaskTotal } from '@/api/approve/all' import { listApprovalTask, getApprovalTaskTotal, addTodoConfirm } from '@/api/approve/all'
import ApproveDialog from '../order/Approve.vue' import ApproveDialog from '../order/Approve.vue'
import { getPurchaseorder } from '@/api/sip/purchaseorder' import { getPurchaseorder } from '@/api/sip/purchaseorder'
import { getPayment } from '@/api/finance/payment' import { getPayment } from '@/api/finance/payment'
@ -480,6 +510,8 @@ import { getInvoiceReceipt } from '@/api/finance/invoiceReceipt'
import { getReceiptDetail } from '@/api/finance/receipt' import { getReceiptDetail } from '@/api/finance/receipt'
import { getInvoiceDetail } from '@/api/finance/invoice' import { getInvoiceDetail } from '@/api/finance/invoice'
import { listCompletedFlows, approveTask } from '@/api/flow' import { listCompletedFlows, approveTask } from '@/api/flow'
import OuterRebackDetail from './components/OuterRebackDetail.vue'
import OrderRebackDetail from './components/OrderRebackDetail.vue'
import PurchaseOrderDetailView from '@/views/purchaseorder/components/PurchaseOrderDetailView.vue' import PurchaseOrderDetailView from '@/views/purchaseorder/components/PurchaseOrderDetailView.vue'
import ApproveLayout from '@/views/approve/ApproveLayout.vue' import ApproveLayout from '@/views/approve/ApproveLayout.vue'
import PaymentDetail from '@/views/approve/finance/payment/components/PaymentDetail.vue' import PaymentDetail from '@/views/approve/finance/payment/components/PaymentDetail.vue'
@ -499,7 +531,9 @@ export default {
PaymentDetail, PaymentDetail,
InvoiceReceiptDetail, InvoiceReceiptDetail,
ReceiptDetail, ReceiptDetail,
ReceivableInvoiceDetail ReceivableInvoiceDetail,
OuterRebackDetail,
OrderRebackDetail
}, },
data() { data() {
return { return {
@ -512,7 +546,8 @@ export default {
tabs: [ tabs: [
{ label: '全部', name: 'all' }, { label: '全部', name: 'all' },
{ label: '待处理', name: 'pending' }, { label: '待处理', name: 'pending' },
{ label: '已通过', name: 'approved' }, { label: '已通过', name: 'processed' },
{ label: '已归档', name: 'approved' },
{ label: '已驳回', name: 'returned' } { label: '已驳回', name: 'returned' }
], ],
queryParams: { queryParams: {
@ -618,7 +653,21 @@ export default {
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }] approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }]
}, },
invoicePdfExporting: false, invoicePdfExporting: false,
invoiceExcelExporting: false invoiceExcelExporting: false,
//
outerRebackDialogVisible: false,
outerRebackDeliveryId: null,
outerRebackOuterCode: '',
outerRebackProcessKey: null,
outerRebackTaskId: null,
outerRebackShowApproveButtons: false,
//
orderRebackDialogVisible: false,
orderRebackOrderId: null,
orderRebackOrderCode: '',
orderRebackProcessKey: null,
orderRebackTaskId: null,
orderRebackShowApproveButtons: false
} }
}, },
created() { created() {
@ -643,7 +692,8 @@ export default {
all: data.allCount || 0, all: data.allCount || 0,
pending: data.pendingCount || 0, pending: data.pendingCount || 0,
approved: data.approvedCount || 0, approved: data.approvedCount || 0,
returned: data.returnedCount || 0 returned: data.returnedCount || 0,
processed: data.processedCount || 0
} }
}) })
}, },
@ -655,7 +705,8 @@ export default {
all: null, all: null,
pending: 1, pending: 1,
approved: 2, approved: 2,
returned: 3 returned: 3,
processed: 4
} }
this.queryParams = { this.queryParams = {
processNo: '', processNo: '',
@ -678,7 +729,8 @@ export default {
all: null, all: null,
pending: 1, pending: 1,
approved: 2, approved: 2,
returned: 3 returned: 3,
processed: 4
} }
this.searchParams = { this.searchParams = {
...this.queryParams, ...this.queryParams,
@ -697,12 +749,42 @@ export default {
this.getList() this.getList()
} }
}, },
isCurrentApproveUser(row) {
const roles = this.$store.getters.roles || []
if (roles.includes('admin')) return true
const userId = String(this.$store.state.user.id)
const approveUser = String(row.approveUser)
return userId === approveUser
},
getApproveStatusLabel(row) {
if (row.approveStatus === '1') {
return this.isCurrentApproveUser(row) ? '待处理' : '已通过'
}
const map = { 2: '已通过', 3: '已驳回' }
return map[row.approveStatus] || ''
},
getApproveStatusTagType(row) {
if (row.approveStatus === '1') {
return this.isCurrentApproveUser(row) ? 'primary' : 'success'
}
const map = { 2: 'success', 3: 'danger' }
return map[row.approveStatus] || 'info'
},
getApproveTypeLabel(value) { getApproveTypeLabel(value) {
if (!value) return '-'
const item = (this.dict.type.approve_type || []).find(d => d.value == value) const item = (this.dict.type.approve_type || []).find(d => d.value == value)
return item ? item.label : '-' return item ? item.label : ''
}, },
isApproveButton(row) { isApproveButton(row) {
if (row.approveStatus !== '1') return false
if (row.confirm === true) return false
const roles = this.$store.getters.roles || []
if (roles.includes('admin')) return true
const userId = String(this.$store.state.user.id)
const approveUser = String(row.approveUser)
return userId === approveUser
},
// confirm/admin
isActionApproveButton(row) {
if (row.approveStatus !== '1') return false if (row.approveStatus !== '1') return false
const roles = this.$store.getters.roles || [] const roles = this.$store.getters.roles || []
if (roles.includes('admin')) return true if (roles.includes('admin')) return true
@ -711,12 +793,16 @@ export default {
return userId === approveUser return userId === approveUser
}, },
getActionButtonText(row) { getActionButtonText(row) {
return this.isApproveButton(row) ? '审批' : '查看' return this.isActionApproveButton(row) ? '审批' : '查看'
}, },
handleAction(row) { handleAction(row) {
//
if (this.isApproveButton(row) && !row._confirmed) {
this.sendTodoConfirm(row)
}
if (row.approveType === 'order_approval') { if (row.approveType === 'order_approval') {
this.currentOrderId = row.id this.currentOrderId = row.id
this.showApproveButtons = this.isApproveButton(row) this.showApproveButtons = this.isActionApproveButton(row)
this.orderDrawerVisible = true this.orderDrawerVisible = true
return return
} }
@ -740,15 +826,33 @@ export default {
this.handleInvoiceApprove(row) this.handleInvoiceApprove(row)
return return
} }
if (row.approveType === 'outer_reback_approval') {
this.handleOuterRebackApprove(row)
return
}
if (row.approveType === 'order_reback_approval') {
this.handleOrderRebackApprove(row)
return
}
this.$message.info(`${this.isApproveButton(row) ? '审批' : '查看'}流程:${row.processNo}`) this.$message.info(`${this.isApproveButton(row) ? '审批' : '查看'}流程:${row.processNo}`)
}, },
// admin/
sendTodoConfirm(row) {
const roles = this.$store.getters.roles || []
if (roles.includes('admin')) return
const { processInstanceId, businessKey, processKey } = row
if (!processInstanceId || !businessKey || !processKey) return
addTodoConfirm({ processInstanceId, businessKey, processKey }).then(() => {
this.$set(row, '_confirmed', true)
}).catch(() => {})
},
handlePurchaseApprove(row) { handlePurchaseApprove(row) {
this.purchaseForm = { omsPurchaseOrderItemList: [] } this.purchaseForm = { omsPurchaseOrderItemList: [] }
this.purchaseApproveLogs = [] this.purchaseApproveLogs = []
this.purchaseOpinionForm.approveOpinion = '' this.purchaseOpinionForm.approveOpinion = ''
this.purchaseProcessKey = row.processKey this.purchaseProcessKey = row.processKey
this.purchaseTaskId = row.taskId this.purchaseTaskId = row.taskId
this.purchaseShowApproveButtons = this.isApproveButton(row) this.purchaseShowApproveButtons = this.isActionApproveButton(row)
this.purchaseDetailLoading = true this.purchaseDetailLoading = true
this.purchaseDialogVisible = true this.purchaseDialogVisible = true
getPurchaseorder(row.id).then(response => { getPurchaseorder(row.id).then(response => {
@ -797,6 +901,7 @@ export default {
this.$modal.msgSuccess(this.purchaseConfirmDialogTitle + '成功') this.$modal.msgSuccess(this.purchaseConfirmDialogTitle + '成功')
this.purchaseDialogVisible = false this.purchaseDialogVisible = false
this.getList() this.getList()
this.getTotal()
}).catch(error => { }).catch(error => {
console.error('审批失败: ', error) console.error('审批失败: ', error)
this.$modal.msgError('审批失败!' + (error.msg || error.message)) this.$modal.msgError('审批失败!' + (error.msg || error.message))
@ -812,7 +917,7 @@ export default {
this.paymentOpinionForm.approveOpinion = '' this.paymentOpinionForm.approveOpinion = ''
this.paymentProcessKey = row.processKey this.paymentProcessKey = row.processKey
this.paymentTaskId = row.taskId this.paymentTaskId = row.taskId
this.paymentShowApproveButtons = this.isApproveButton(row) this.paymentShowApproveButtons = this.isActionApproveButton(row)
this.paymentDetailLoading = true this.paymentDetailLoading = true
this.paymentDialogVisible = true this.paymentDialogVisible = true
getPayment(row.id).then(response => { getPayment(row.id).then(response => {
@ -862,6 +967,7 @@ export default {
this.$modal.msgSuccess(this.paymentConfirmDialogTitle + '成功') this.$modal.msgSuccess(this.paymentConfirmDialogTitle + '成功')
this.paymentDialogVisible = false this.paymentDialogVisible = false
this.getList() this.getList()
this.getTotal()
}).catch(error => { }).catch(error => {
console.error('审批失败: ', error) console.error('审批失败: ', error)
this.$modal.msgError('审批失败!' + (error.msg || error.message)) this.$modal.msgError('审批失败!' + (error.msg || error.message))
@ -891,7 +997,7 @@ export default {
this.ticketOpinionForm.approveOpinion = '' this.ticketOpinionForm.approveOpinion = ''
this.ticketProcessKey = row.processKey this.ticketProcessKey = row.processKey
this.ticketTaskId = row.taskId this.ticketTaskId = row.taskId
this.ticketShowApproveButtons = this.isApproveButton(row) this.ticketShowApproveButtons = this.isActionApproveButton(row)
this.ticketDetailLoading = true this.ticketDetailLoading = true
this.ticketDialogVisible = true this.ticketDialogVisible = true
getInvoiceReceipt(row.id).then(response => { getInvoiceReceipt(row.id).then(response => {
@ -972,7 +1078,7 @@ export default {
this.receiptOpinionForm.approveOpinion = '' this.receiptOpinionForm.approveOpinion = ''
this.receiptProcessKey = row.processKey this.receiptProcessKey = row.processKey
this.receiptTaskId = row.taskId this.receiptTaskId = row.taskId
this.receiptShowApproveButtons = this.isApproveButton(row) this.receiptShowApproveButtons = this.isActionApproveButton(row)
this.receiptDetailLoading = true this.receiptDetailLoading = true
this.receiptDialogVisible = true this.receiptDialogVisible = true
getReceiptDetail(row.id).then(response => { getReceiptDetail(row.id).then(response => {
@ -1022,6 +1128,7 @@ export default {
this.$modal.msgSuccess(this.receiptConfirmDialogTitle + '成功') this.$modal.msgSuccess(this.receiptConfirmDialogTitle + '成功')
this.receiptDialogVisible = false this.receiptDialogVisible = false
this.getList() this.getList()
this.getTotal()
}).catch(error => { }).catch(error => {
console.error('审批失败: ', error) console.error('审批失败: ', error)
this.$modal.msgError('审批失败!' + (error.msg || error.message)) this.$modal.msgError('审批失败!' + (error.msg || error.message))
@ -1051,7 +1158,7 @@ export default {
this.invoiceOpinionForm.approveOpinion = '' this.invoiceOpinionForm.approveOpinion = ''
this.invoiceProcessKey = row.processKey this.invoiceProcessKey = row.processKey
this.invoiceTaskId = row.taskId this.invoiceTaskId = row.taskId
this.invoiceShowApproveButtons = this.isApproveButton(row) this.invoiceShowApproveButtons = this.isActionApproveButton(row)
this.invoiceDetailLoading = true this.invoiceDetailLoading = true
this.invoiceDialogVisible = true this.invoiceDialogVisible = true
getInvoiceDetail(row.id).then(response => { getInvoiceDetail(row.id).then(response => {
@ -1101,6 +1208,7 @@ export default {
this.$modal.msgSuccess(this.invoiceConfirmDialogTitle + '成功') this.$modal.msgSuccess(this.invoiceConfirmDialogTitle + '成功')
this.invoiceDialogVisible = false this.invoiceDialogVisible = false
this.getList() this.getList()
this.getTotal()
}).catch(error => { }).catch(error => {
console.error('审批失败: ', error) console.error('审批失败: ', error)
this.$modal.msgError('审批失败!' + (error.msg || error.message)) this.$modal.msgError('审批失败!' + (error.msg || error.message))
@ -1141,6 +1249,32 @@ export default {
this.invoiceExcelExporting = false this.invoiceExcelExporting = false
} }
}, },
handleOuterRebackApprove(row) {
this.outerRebackDeliveryId = row.id
this.outerRebackOuterCode = row.processNo
this.outerRebackProcessKey = row.processKey
this.outerRebackTaskId = row.taskId
this.outerRebackShowApproveButtons = this.isActionApproveButton(row)
this.outerRebackDialogVisible = true
},
//
handleOuterRebackApproved() {
this.getList()
this.getTotal()
},
handleOrderRebackApprove(row) {
this.orderRebackOrderId = row.id
this.orderRebackOrderCode = row.processNo
this.orderRebackProcessKey = row.processKey
this.orderRebackTaskId = row.taskId
this.orderRebackShowApproveButtons = this.isActionApproveButton(row)
this.orderRebackDialogVisible = true
},
//
handleOrderRebackApproved() {
this.getList()
this.getTotal()
},
closeOrderDrawer() { closeOrderDrawer() {
this.orderDrawerVisible = false this.orderDrawerVisible = false
this.currentOrderId = null this.currentOrderId = null

View File

@ -61,7 +61,10 @@
</div> </div>
<div class="section" style="margin-top: 20px;"> <div class="section" style="margin-top: 20px;">
<div class="el-descriptions__title">附件信息</div> <div style="display: flex; justify-content: space-between; align-items: center;">
<div class="el-descriptions__title">附件信息</div>
<el-button type="success" size="mini" icon="el-icon-download" :loading="zipDownloading" @click="handleDownloadAllAttachments"></el-button>
</div>
<el-table :data="data.fileList" border style="width: 100%; margin-top: 10px;"> <el-table :data="data.fileList" border style="width: 100%; margin-top: 10px;">
<el-table-column prop="fileName" label="附件名称" align="center"></el-table-column> <el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>
<el-table-column prop="createTime" label="上传时间" align="center"></el-table-column> <el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>
@ -113,6 +116,8 @@
<script> <script>
import request from '@/utils/request'; import request from '@/utils/request';
import JSZip from 'jszip';
import { saveAs } from 'file-saver';
import { getPurchaseorder } from "@/api/sip/purchaseorder"; import { getPurchaseorder } from "@/api/sip/purchaseorder";
import {formatCurrency} from "@/utils"; import {formatCurrency} from "@/utils";
import EditForm from "@/views/finance/payable/components/EditForm.vue"; import EditForm from "@/views/finance/payable/components/EditForm.vue";
@ -134,6 +139,7 @@ export default {
data() { data() {
return { return {
attachments: [], attachments: [],
zipDownloading: false,
pdfPreviewVisible: false, pdfPreviewVisible: false,
currentPdfUrl: '', currentPdfUrl: '',
imagePreviewVisible: false, imagePreviewVisible: false,
@ -187,6 +193,37 @@ export default {
link.click(); link.click();
document.body.removeChild(link); document.body.removeChild(link);
}, },
async handleDownloadAllAttachments() {
const files = Array.isArray(this.data.fileList) ? this.data.fileList : [];
if (files.length === 0) {
this.$modal.msgWarning('暂无可下载的附件');
return;
}
this.zipDownloading = true;
this.$modal.loading('正在打包附件,请稍候...');
try {
const zip = new JSZip();
for (const row of files) {
const blob = await request({
url: '/common/download/resource',
method: 'get',
params: { resource: row.filePath },
responseType: 'blob',
timeout: 0
}).then(res => res.data);
zip.file(row.fileName || 'file', blob);
}
const content = await zip.generateAsync({ type: 'blob' });
saveAs(content, (this.data.paymentBillCode || '付款申请单附件') + '.zip');
this.$modal.msgSuccess('下载成功');
} catch (error) {
console.error('附件打包下载失败', error);
this.$modal.msgError('附件下载失败,请稍后重试');
} finally {
this.zipDownloading = false;
this.$modal.closeLoading();
}
},
handleViewPayable(row) { handleViewPayable(row) {
row.id = row.payableBillId; row.id = row.payableBillId;
this.selectedPayableRow = row; this.selectedPayableRow = row;

View File

@ -171,12 +171,12 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="审批通过时间" align="center" prop="approveTime" width="120" > <!--<el-table-column label="审批通过时间" align="center" prop="approveTime" width="120" >
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ timeProcessing(scope.row.approveTime) }}</span> <span>{{ timeProcessing(scope.row.approveTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="审批节点" align="center" prop="approveNode" width="100" fixed="right"/> <el-table-column label="审批节点" align="center" prop="approveNode" width="100" fixed="right"/>-->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width operation-column" width="100" fixed="right"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width operation-column" width="100" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button

View File

@ -1,9 +1,9 @@
<template> <template>
<el-drawer title="采购 - 应付单详情" :visible.sync="internalVisible" :wrapper-closable="false" size="70%" :z-index="zIndex" @close="handleClose"> <el-drawer title="应付单详情" :visible.sync="internalVisible" :wrapper-closable="false" size="70%" :z-index="zIndex" @close="handleClose">
<div class="dialog-body" v-loading="loading" element-loading-text="数据加载中..."> <div class="dialog-body" v-loading="loading" element-loading-text="数据加载中...">
<!-- Part 1: Details --> <!-- Part 1: Details -->
<div> <div>
<el-divider content-position="left">采购-应付单</el-divider> <el-divider content-position="left">应付单</el-divider>
<div class="details-container"> <div class="details-container">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
@ -13,7 +13,7 @@
<div class="detail-item"><strong>项目名称:</strong> {{ formData.projectName }}</div> <div class="detail-item"><strong>项目名称:</strong> {{ formData.projectName }}</div>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<div class="detail-item"><strong>采购-应付单编号:</strong> {{ formData.payableBillCode }}</div> <div class="detail-item"><strong>应付单编号:</strong> {{ formData.payableBillCode }}</div>
</el-col> </el-col>
</el-row> </el-row>
@ -114,7 +114,7 @@
</el-table> </el-table>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="付款计划" name="paymentPlan"> <el-tab-pane label="付款计划" name="paymentPlan">
<el-divider content-position="left">采购-付款单</el-divider> <el-divider content-position="left">付款单</el-divider>
<el-table :data="formData.detailList" style="width: 100%" show-summary :summary-method="getSummaries"> <el-table :data="formData.detailList" style="width: 100%" show-summary :summary-method="getSummaries">
<el-table-column type="index" label="序号" width="50"></el-table-column> <el-table-column type="index" label="序号" width="50"></el-table-column>
<el-table-column prop="payableDetailType" label="付款通道"> <el-table-column prop="payableDetailType" label="付款通道">
@ -138,7 +138,7 @@
<dict-tag :options="dict.type.payment_status" :value="scope.row.paymentStatus"/> <dict-tag :options="dict.type.payment_status" :value="scope.row.paymentStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="paymentBillCode" label="采购-付款单编号"> <el-table-column prop="paymentBillCode" label="付款单编号">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
v-if="scope.row.paymentBillCode" v-if="scope.row.paymentBillCode"
@ -161,7 +161,7 @@
<PaymentPlan :isInitEdit=true @syncPlan="refreshTicketPlan()" :payableData="data"/> <PaymentPlan :isInitEdit=true @syncPlan="refreshTicketPlan()" :payableData="data"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="收票计划" name="receivingTicketPlan"> <el-tab-pane label="收票计划" name="receivingTicketPlan">
<el-divider content-position="left">采购-收票单</el-divider> <el-divider content-position="left">收票单</el-divider>
<el-table :data="formData.ticketDetailList" style="width: 100%" show-summary :summary-method="getSummaries"> <el-table :data="formData.ticketDetailList" style="width: 100%" show-summary :summary-method="getSummaries">
<el-table-column type="index" label="序号" width="50"></el-table-column> <el-table-column type="index" label="序号" width="50"></el-table-column>
<el-table-column prop="payableDetailType" label="发票类型"> <el-table-column prop="payableDetailType" label="发票类型">
@ -186,7 +186,7 @@
<dict-tag :options="dict.type.receipt_status" :value="scope.row.ticketStatus"/> <dict-tag :options="dict.type.receipt_status" :value="scope.row.ticketStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="ticketBillCode" label="采购-收票单编号"> <el-table-column prop="ticketBillCode" label="收票单编号">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
v-if="scope.row.ticketBillCode" v-if="scope.row.ticketBillCode"

View File

@ -38,9 +38,9 @@
</el-row> </el-row>
</el-form> </el-form>
<el-divider content-position="left">采购应付单表</el-divider> <el-divider content-position="left">应付单表</el-divider>
<el-table :data="payableOrdersWithPlans" border max-height="300px" style="margin-bottom: 20px;"> <el-table :data="payableOrdersWithPlans" border max-height="300px" style="margin-bottom: 20px;">
<el-table-column label="采购-应付单编号" align="center" prop="payableBillCode" width="150"/> <el-table-column label="应付单编号" align="center" prop="payableBillCode" width="150"/>
<el-table-column label="预计付款时间" align="center" prop="planPaymentDate" width="180"/> <el-table-column label="预计付款时间" align="center" prop="planPaymentDate" width="180"/>
<el-table-column label="预期付款计划" align="center" width="100" prop="planAmount"> <el-table-column label="预期付款计划" align="center" width="100" prop="planAmount">
<template slot-scope="scope"> <template slot-scope="scope">

View File

@ -48,9 +48,9 @@
</el-row> </el-row>
</el-form> </el-form>
<el-divider content-position="left">采购应付单表</el-divider> <el-divider content-position="left">应付单表</el-divider>
<el-table :data="payableOrdersWithPlans" border max-height="300px" style="margin-bottom: 20px;"> <el-table :data="payableOrdersWithPlans" border max-height="300px" style="margin-bottom: 20px;">
<el-table-column label="采购-应付单编号" align="center" prop="payableBillCode" width="150"/> <el-table-column label="应付单编号" align="center" prop="payableBillCode" width="150"/>
<el-table-column label="预计收票时间" align="center" prop="planTicketDate" width="180"/> <el-table-column label="预计收票时间" align="center" prop="planTicketDate" width="180"/>
<!-- <el-table-column label="收票计划" align="center" width="100" prop="planTicketAmount">--> <!-- <el-table-column label="收票计划" align="center" width="100" prop="planTicketAmount">-->
<!-- </el-table-column>--> <!-- </el-table-column>-->

View File

@ -17,7 +17,7 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="采购-应付单编号" prop="payableBillCode"> <el-form-item label="应付单编号" prop="payableBillCode">
<el-input <el-input
v-model="queryParams.payableBillCode" v-model="queryParams.payableBillCode"
placeholder="请输入应付单编号" placeholder="请输入应付单编号"
@ -126,7 +126,7 @@
<el-table-column type="selection" width="50" /> <el-table-column type="selection" width="50" />
<el-table-column label="项目编号" align="center" prop="projectCode" width="120" /> <el-table-column label="项目编号" align="center" prop="projectCode" width="120" />
<el-table-column label="项目名称" align="center" prop="projectName" width="260" /> <el-table-column label="项目名称" align="center" prop="projectName" width="260" />
<el-table-column label="采购-应付单编号" align="center" prop="payableBillCode" width="150" /> <el-table-column label="应付单编号" align="center" prop="payableBillCode" width="150" />
<!-- <el-table-column label="生成时间" align="center" prop="createTime" width="180"/>--> <!-- <el-table-column label="生成时间" align="center" prop="createTime" width="180"/>-->
<el-table-column label="预计付款时间" align="center" prop="planPaymentDate" width="120"> <el-table-column label="预计付款时间" align="center" prop="planPaymentDate" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
@ -258,7 +258,7 @@ export default {
showSearch: true, showSearch: true,
// //
total: 0, total: 0,
// //
payableList: [], payableList: [],
// //
dateRange: [], dateRange: [],
@ -304,7 +304,7 @@ export default {
this.getList(); this.getList();
}, },
methods: { methods: {
/** 查询采购应付单列表 */ /** 查询应付单列表 */
getList() { getList() {
this.loading = true; this.loading = true;
const queryParams = { ...this.queryParams }; const queryParams = { ...this.queryParams };
@ -351,7 +351,7 @@ export default {
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
this.$modal.confirm('是否确认删除采购应付单编号为"' + row.payableBillCode + '"的数据项?').then(function() { this.$modal.confirm('是否确认删除应付单编号为"' + row.payableBillCode + '"的数据项?').then(function() {
return Promise.resolve(); return Promise.resolve();
}).then(() => { }).then(() => {
this.$modal.msgSuccess("删除成功"); this.$modal.msgSuccess("删除成功");

View File

@ -64,7 +64,7 @@
<!-- Tables --> <!-- Tables -->
<div v-if="form.vendorCode"> <div v-if="form.vendorCode">
<div v-if="form.paymentBillType === 'FROM_PAYABLE'" class="table-container"> <div v-if="form.paymentBillType === 'FROM_PAYABLE'" class="table-container">
<h4>采购-应付单表</h4> <h4>应付单表</h4>
<el-table <el-table
ref="payableTable" ref="payableTable"
:data="payableList" :data="payableList"
@ -76,7 +76,7 @@
:summary-method="getPayableSummary" :summary-method="getPayableSummary"
> >
<el-table-column type="selection" width="55" reserve-selection></el-table-column> <el-table-column type="selection" width="55" reserve-selection></el-table-column>
<el-table-column label="采购-应付单编号" align="center" prop="payableBillCode" width="150"/> <el-table-column label="应付单编号" align="center" prop="payableBillCode" width="150"/>
<el-table-column label="预计付款时间" align="center" prop="planPaymentDate" width="180"/> <el-table-column label="预计付款时间" align="center" prop="planPaymentDate" width="180"/>
<el-table-column label="预期付款计划" align="center" width="100" prop="planAmount"> <el-table-column label="预期付款计划" align="center" width="100" prop="planAmount">
<template slot-scope="scope"> <template slot-scope="scope">

View File

@ -11,7 +11,7 @@
> >
<div class="dialog-body" v-if="detail" ref="paymentDrawer"> <div class="dialog-body" v-if="detail" ref="paymentDrawer">
<div class="section"> <div class="section">
<el-divider content-position="left">采购-付款单</el-divider> <el-divider content-position="left">付款单</el-divider>
<div class="section-actions"> <div class="section-actions">
<el-button type="primary" size="mini" :loading="pdfExporting" @click="handleExportPDF">PDF</el-button> <el-button type="primary" size="mini" :loading="pdfExporting" @click="handleExportPDF">PDF</el-button>
<el-button size="mini" @click="handlePrint"></el-button> <el-button size="mini" @click="handlePrint"></el-button>
@ -20,7 +20,7 @@
<div class="details-container"> <div class="details-container">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
<div class="detail-item">采购-付款单编号: {{ detail.paymentBillCode }}</div> <div class="detail-item">付款单编号: {{ detail.paymentBillCode }}</div>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<div class="detail-item">预计付款时间: {{ detail.paymentTime }}</div> <div class="detail-item">预计付款时间: {{ detail.paymentTime }}</div>
@ -100,6 +100,7 @@
<div class="detail-item">特别说明: {{ detail.remark }}</div> <div class="detail-item">特别说明: {{ detail.remark }}</div>
</el-col> </el-col>
</el-row> </el-row>
<el-button type="success" size="mini" icon="el-icon-download" :loading="zipDownloading" @click="handleDownloadAllAttachments" style="margin-bottom: 10px">一键下载附件</el-button>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="24"> <el-col :span="24">
<div class="detail-item"> <div class="detail-item">
@ -121,12 +122,12 @@
</div> </div>
<div class="section"> <div class="section">
<el-divider content-position="left">采购-应付单</el-divider> <el-divider content-position="left">应付单</el-divider>
<el-table :data="detail.payableDetails"> <el-table :data="detail.payableDetails">
<el-table-column type="index" label="序号" width="50"></el-table-column> <el-table-column type="index" label="序号" width="50"></el-table-column>
<el-table-column property="projectCode" label="项目编号"></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="projectName" label="项目名称"></el-table-column>
<el-table-column label="采购应付单编号"> <el-table-column label="应付单编号">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" @click="handleViewPayable(scope.row)" >{{ scope.row.payableBillCode }}</el-button> <el-button type="text" @click="handleViewPayable(scope.row)" >{{ scope.row.payableBillCode }}</el-button>
</template> </template>
@ -157,6 +158,9 @@
</template> </template>
<script> <script>
import request from "@/utils/request";
import JSZip from "jszip";
import { saveAs } from "file-saver";
import FileUpload from "@/components/FileUpload"; import FileUpload from "@/components/FileUpload";
import EditForm from "@/views/finance/payable/components/EditForm.vue"; import EditForm from "@/views/finance/payable/components/EditForm.vue";
import FlowOpinionTimeline from "@/views/finance/components/FlowOpinionTimeline.vue"; import FlowOpinionTimeline from "@/views/finance/components/FlowOpinionTimeline.vue";
@ -190,6 +194,7 @@ export default {
approveLogsTimer: null, approveLogsTimer: null,
approveLogsLoading: false, approveLogsLoading: false,
pdfExporting: false, pdfExporting: false,
zipDownloading: false,
}; };
}, },
beforeDestroy() { beforeDestroy() {
@ -254,6 +259,61 @@ export default {
}; };
this.$emit('submit', saveData); this.$emit('submit', saveData);
}, },
getAllAttachments() {
const saved = Array.isArray(this.detail.fileList) ? this.detail.fileList : [];
//
const supplement = Array.isArray(this.fileList) ? this.fileList : [];
const result = [];
saved.forEach(att => {
if (att && (att.filePath || att.url)) {
result.push({ fileName: att.fileName || this.getFileBaseName(att.filePath || att.url), filePath: att.filePath || att.url });
}
});
supplement.forEach(att => {
if (att && (att.url || att.filePath)) {
const filePath = att.url || att.filePath;
result.push({ fileName: att.name || att.fileName || this.getFileBaseName(filePath), filePath });
}
});
return result;
},
getFileBaseName(path) {
if (!path) return 'file';
const parts = path.split('/');
return parts[parts.length - 1] || 'file';
},
async handleDownloadAllAttachments() {
const attachments = this.getAllAttachments();
if (attachments.length === 0) {
this.$modal.msgWarning('暂无可下载的附件');
return;
}
this.zipDownloading = true;
this.$modal.loading('正在打包附件,请稍候...');
try {
const zip = new JSZip();
const folder = zip.folder(this.detail.paymentBillCode || '付款单附件');
for (const att of attachments) {
const blob = await request({
url: '/common/download/resource',
method: 'get',
params: { resource: att.filePath },
responseType: 'blob',
timeout: 0
}).then(res => res.data);
folder.file(att.fileName || 'file', blob);
}
const content = await zip.generateAsync({ type: 'blob' });
saveAs(content, (this.detail.paymentBillCode || '付款单附件') + '.zip');
this.$modal.msgSuccess('下载成功');
} catch (error) {
console.error('附件打包下载失败', error);
this.$modal.msgError('附件下载失败,请稍后重试');
} finally {
this.zipDownloading = false;
this.$modal.closeLoading();
}
},
handleViewPayable(row) { handleViewPayable(row) {
row.id = row.payableBillId; row.id = row.payableBillId;
this.selectedPayableRow = row; this.selectedPayableRow = row;

View File

@ -17,7 +17,7 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="采购-付款单编号" prop="paymentBillCode"> <el-form-item label="付款单编号" prop="paymentBillCode">
<el-input <el-input
v-model="queryParams.paymentBillCode" v-model="queryParams.paymentBillCode"
placeholder="请输入付款单编号" placeholder="请输入付款单编号"
@ -33,7 +33,7 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="采购-应付单编号" prop="payableBillCode"> <el-form-item label="应付单编号" prop="payableBillCode">
<el-input <el-input
v-model="queryParams.payableBillCode" v-model="queryParams.payableBillCode"
placeholder="请输入应付单编号" placeholder="请输入应付单编号"
@ -151,7 +151,7 @@
<el-table v-loading="loading" :data="paymentList" show-summary :summary-method="getSummaries"> <el-table v-loading="loading" :data="paymentList" show-summary :summary-method="getSummaries">
<el-table-column label="项目编号" align="center" prop="projectCode" width="120" /> <el-table-column label="项目编号" align="center" prop="projectCode" width="120" />
<el-table-column label="项目名称" align="center" prop="projectName" width="260" /> <el-table-column label="项目名称" align="center" prop="projectName" width="260" />
<el-table-column label="采购-付款单编号" width="200" align="center" prop="paymentBillCode"> <el-table-column label="付款单编号" width="200" align="center" prop="paymentBillCode">
<template slot-scope="scope"> <template slot-scope="scope">
<a @click="handleDetail(scope.row)" class="link-type">{{ scope.row.paymentBillCode }}</a> <a @click="handleDetail(scope.row)" class="link-type">{{ scope.row.paymentBillCode }}</a>
</template> </template>
@ -193,12 +193,12 @@
<dict-tag :options="dict.type.approve_status" :value="scope.row.approveStatus"/> <dict-tag :options="dict.type.approve_status" :value="scope.row.approveStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="审批通过时间" align="center" prop="approveTime" width="120"> <!--<el-table-column label="审批通过时间" align="center" prop="approveTime" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ timeProcessing(scope.row.approveTime) }}</span> <span>{{ timeProcessing(scope.row.approveTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="审批节点" fixed="right" width="80" align="center" prop="approveNode"/> <el-table-column label="审批节点" fixed="right" width="80" align="center" prop="approveNode"/>-->
<el-table-column label="操作" fixed="right" width="100" align="center" class-name="small-padding fixed-width operation-column"> <el-table-column label="操作" fixed="right" width="100" align="center" class-name="small-padding fixed-width operation-column">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
@ -218,7 +218,7 @@
size="mini" size="mini"
type="text" type="text"
icon="el-icon-position" icon="el-icon-position"
v-show="(scope.row.approveStatus==='0' || scope.row.approveStatus==='3') && (scope.row.paymentBillType==='FROM_PAYABLE'||scope.row.paymentBillType==='PRE_PAYMENT')" v-show="(scope.row.approveStatus==='0' || scope.row.approveStatus==='3') && (scope.row.paymentBillType==='FROM_PAYABLE'||scope.row.paymentBillType==='PRE_PAYMENT'||scope.row.paymentBillType==='REFUND')"
@click="applyPayment(scope.row)" @click="applyPayment(scope.row)"
>申请付款</el-button> >申请付款</el-button>
@ -233,9 +233,10 @@
size="mini" size="mini"
type="text" type="text"
icon="el-icon-refresh-right" icon="el-icon-refresh-right"
v-if="canApplyRefund(scope.row) && false" v-if="canApplyRefund(scope.row)"
@click="handleApplyRefund(scope.row)" @click="handleApplyRefund(scope.row)"
>申请退款</el-button> >申请退款</el-button>
<!-- 撤销按钮已按要求注释
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
@ -243,12 +244,13 @@
v-if="(scope.row.approveStatus === '2' || scope.row.approveStatus==='3') && (scope.row.paymentStatus==='1'||scope.row.paymentStatus==='3')" v-if="(scope.row.approveStatus === '2' || scope.row.approveStatus==='3') && (scope.row.paymentStatus==='1'||scope.row.paymentStatus==='3')"
@click="handleRevoke(scope.row)" @click="handleRevoke(scope.row)"
>撤销</el-button> >撤销</el-button>
-->
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-delete" icon="el-icon-delete"
v-hasPermi="['finance:payment:remove']" v-hasPermi="['finance:payment:remove']"
v-show="(scope.row.approveStatus==='0' || scope.row.approveStatus==='3') && scope.row.paymentBillType==='PRE_PAYMENT' && scope.row.paymentStatus === '1' " v-show="(scope.row.approveStatus==='0' || scope.row.approveStatus==='3') && (scope.row.paymentBillType==='PRE_PAYMENT' || scope.row.paymentBillType==='REFUND') && scope.row.paymentStatus === '1' "
@click="handleDelete(scope.row.id)" @click="handleDelete(scope.row.id)"
>删除 >删除
</el-button> </el-button>
@ -272,7 +274,7 @@
<receipt-dialog :visible.sync="receiptOpen" :payment-data="currentRow" :dicts="dict.type"></receipt-dialog> <receipt-dialog :visible.sync="receiptOpen" :payment-data="currentRow" :dicts="dict.type"></receipt-dialog>
<!-- 付款申请弹窗 --> <!-- 付款申请弹窗 -->
<el-dialog title="发起付款" :visible.sync="applyPaymentOpen" width="600px" append-to-body> <el-dialog title="发起付款" :visible.sync="applyPaymentOpen" width="600px" append-to-body>
<el-form ref="applyPaymentForm" :model="applyPaymentForm" label-width="120px"> <el-form ref="applyPaymentForm" :model="applyPaymentForm" :rules="applyPaymentRules" label-width="120px">
<el-form-item label="支付方式" prop="paymentMethod"> <el-form-item label="支付方式" prop="paymentMethod">
<el-select v-model="applyPaymentForm.paymentMethod" placeholder="请选择支付方式"> <el-select v-model="applyPaymentForm.paymentMethod" placeholder="请选择支付方式">
<el-option <el-option
@ -427,6 +429,9 @@ export default {
// //
applyPaymentOpen: false, applyPaymentOpen: false,
applyPaymentForm: {}, applyPaymentForm: {},
applyPaymentRules: {
paymentMethod: [{ required: true, message: "请选择支付方式", trigger: "change" }]
},
// 退 // 退
applyRefundOpen: false, applyRefundOpen: false,
applyRefundTaxRate: null, applyRefundTaxRate: null,
@ -470,13 +475,17 @@ export default {
}, },
/** 提交付款申请 */ /** 提交付款申请 */
submitApplyPayment() { submitApplyPayment() {
applyPaymentApi(this.applyPaymentForm).then(response => { this.$refs.applyPaymentForm.validate(valid => {
this.$modal.msgSuccess("付款申请提交成功"); if (valid) {
this.applyPaymentOpen = false; applyPaymentApi(this.applyPaymentForm).then(response => {
this.getList(); this.$modal.msgSuccess("付款申请提交成功");
}).catch(error => { this.applyPaymentOpen = false;
console.error("付款申请提交失败", error); this.getList();
this.$modal.msgError("付款申请提交失败"); }).catch(error => {
console.error("付款申请提交失败", error);
this.$modal.msgError("付款申请提交失败");
});
}
}); });
}, },
getList() { getList() {
@ -555,7 +564,7 @@ export default {
}, },
/** 退回按钮操作 */ /** 退回按钮操作 */
handleReturn(row) { handleReturn(row) {
this.$modal.confirm('是否将该笔采购-付款单退回至采购-应付单').then(function() { this.$modal.confirm('是否将该笔付款单退回至应付单').then(function() {
return returnPayment(row.id); return returnPayment(row.id);
}).then(() => { }).then(() => {
this.getList(); this.getList();
@ -597,7 +606,7 @@ export default {
}, },
canApplyRefund(row) { canApplyRefund(row) {
const remainingRefundAmount = Number(row.remainingRefundAmount); const remainingRefundAmount = Number(row.remainingRefundAmount);
return row.paymentBillType !== 'REFUND' return row.paymentBillType === 'PRE_PAYMENT'
&& row.paymentStatus === '2' && row.paymentStatus === '2'
&& ['WAIT_REFUNDED', 'PART_REFUNDED', null, undefined, ''].includes(row.refundStatus) && ['WAIT_REFUNDED', 'PART_REFUNDED', null, undefined, ''].includes(row.refundStatus)
&& !Number.isNaN(remainingRefundAmount) && !Number.isNaN(remainingRefundAmount)
@ -681,7 +690,7 @@ export default {
}).catch(() => {}); }).catch(() => {});
}, },
handleRevoke(row) { handleRevoke(row) {
let msg=row.paymentBillType==='REFUND'?'是否将该笔采购-退款单撤销,将退款单撤销至付款单':'是否将该笔采购-付款单撤销,撤销至付款单未审批状态'; let msg=row.paymentBillType==='REFUND'?'是否将该笔退款单撤销,将退款单撤销至付款单':'是否将该笔付款单撤销,撤销至付款单未审批状态';
this.$modal.confirm(msg).then(() => { this.$modal.confirm(msg).then(() => {
return handleRevoke(row.id); return handleRevoke(row.id);
}).then(() => { }).then(() => {

View File

@ -51,7 +51,7 @@
</el-row> </el-row>
</el-form> </el-form>
<el-divider content-position="left">采购应付单表</el-divider> <el-divider content-position="left">应付单表</el-divider>
<el-table <el-table
:data="payableOrdersWithPlans" :data="payableOrdersWithPlans"
border border
@ -62,7 +62,7 @@
ref="table" ref="table"
> >
<el-table-column type="selection" :reserve-selection="true" width="55" align="center" /> <el-table-column type="selection" :reserve-selection="true" width="55" align="center" />
<el-table-column label="采购-应付单编号" align="center" prop="payableBillCode" width="150"/> <el-table-column label="应付单编号" align="center" prop="payableBillCode" width="150"/>
<el-table-column label="预计收票时间" align="center" prop="planTicketDate" width="180"/> <el-table-column label="预计收票时间" align="center" prop="planTicketDate" width="180"/>
<!-- <el-table-column label="收票计划" align="center" width="100" prop="planTicketAmount">--> <!-- <el-table-column label="收票计划" align="center" width="100" prop="planTicketAmount">-->
<!-- </el-table-column>--> <!-- </el-table-column>-->

View File

@ -10,11 +10,11 @@
> >
<div class="dialog-body" v-if="detail"> <div class="dialog-body" v-if="detail">
<div class="section"> <div class="section">
<el-divider content-position="left">采购-收票单</el-divider> <el-divider content-position="left">收票单</el-divider>
<div class="details-container"> <div class="details-container">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
<div class="detail-item">采购-收票单编号: {{ detail.ticketBillCode }}</div> <div class="detail-item">收票单编号: {{ detail.ticketBillCode }}</div>
</el-col> </el-col>
<!-- <el-col :span="8">--> <!-- <el-col :span="8">-->
<!-- <div class="detail-item">预计收票时间: {{ detail.ticketTime }}</div>--> <!-- <div class="detail-item">预计收票时间: {{ detail.ticketTime }}</div>-->
@ -77,12 +77,12 @@
</div> </div>
<div class="section"> <div class="section">
<el-divider content-position="left">采购 - 应付单</el-divider> <el-divider content-position="left">应付单</el-divider>
<el-table :data="detail.detailList"> <el-table :data="detail.detailList">
<el-table-column type="index" label="序号" width="50"></el-table-column> <el-table-column type="index" label="序号" width="50"></el-table-column>
<el-table-column property="projectCode" label="项目编号"></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="projectName" label="项目名称"></el-table-column>
<el-table-column label="采购应付单编号"> <el-table-column label="应付单编号">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" @click="handleViewPayable(scope.row)">{{ scope.row.payableBillCode }}</el-button> <el-button type="text" @click="handleViewPayable(scope.row)">{{ scope.row.payableBillCode }}</el-button>
</template> </template>

View File

@ -17,7 +17,7 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="采购-收票单编号" prop="ticketBillCode"> <el-form-item label="收票单编号" prop="ticketBillCode">
<el-input <el-input
v-model="queryParams.ticketBillCode" v-model="queryParams.ticketBillCode"
placeholder="请输入收票单编号" placeholder="请输入收票单编号"
@ -33,7 +33,7 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="采购-应付单编号" prop="payableBillCode"> <el-form-item label="应付单编号" prop="payableBillCode">
<el-input <el-input
v-model="queryParams.payableBillCode" v-model="queryParams.payableBillCode"
placeholder="请输入应付单编号" placeholder="请输入应付单编号"
@ -128,7 +128,7 @@
</el-row> </el-row>
<el-table v-loading="loading" :data="receiptList" show-summary :summary-method="getSummaries"> <el-table v-loading="loading" :data="receiptList" show-summary :summary-method="getSummaries">
<el-table-column label="采购-收票单编号" align="center" prop="ticketBillCode" width="180" /> <el-table-column label="收票单编号" align="center" prop="ticketBillCode" width="180" />
<!-- <el-table-column label="预计收票时间" align="center" prop="ticketTime" width="180">--> <!-- <el-table-column label="预计收票时间" align="center" prop="ticketTime" width="180">-->
<!-- <template slot-scope="scope">--> <!-- <template slot-scope="scope">-->
<!-- <span>{{ parseTime(scope.row.ticketTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>--> <!-- <span>{{ parseTime(scope.row.ticketTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>-->
@ -176,12 +176,12 @@
<dict-tag :options="dict.type.approve_status" :value="scope.row.approveStatus"/> <dict-tag :options="dict.type.approve_status" :value="scope.row.approveStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="审批通过时间" align="center" prop="approveTime" width="120"> <!--<el-table-column label="审批通过时间" align="center" prop="approveTime" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ timeProcessing(scope.row.approveTime) }}</span> <span>{{ timeProcessing(scope.row.approveTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="审批节点" align="center" prop="approveNode" width="100" /> <el-table-column label="审批节点" align="center" prop="approveNode" width="100" />-->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width operation-column"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width operation-column">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
@ -408,7 +408,7 @@ export default {
}, },
/** 退回按钮操作 */ /** 退回按钮操作 */
handleReturn(row) { handleReturn(row) {
this.$modal.confirm('是否将该笔采购-收票单退回至采购-应付单').then(function() { this.$modal.confirm('是否将该笔收票单退回至应付单').then(function() {
return returnReceipt(row.id); return returnReceipt(row.id);
}).then(() => { }).then(() => {
this.getList(); this.getList();
@ -417,8 +417,8 @@ export default {
}, },
handleRevoke(row) { handleRevoke(row) {
const msg = row.ticketBillType === 'FROM_PAYABLE' const msg = row.ticketBillType === 'FROM_PAYABLE'
? '是否将该笔采购-收票单撤销,撤销后重新上传发票' ? '是否将该笔收票单撤销,撤销后重新上传发票'
: '是否将该笔采购-红冲收票单撤销,将红冲收票单撤销至收票单'; : '是否将该笔红冲收票单撤销,将红冲收票单撤销至收票单';
this.$modal.confirm(msg).then(function() { this.$modal.confirm(msg).then(function() {
return revokeReceipt(row.id); return revokeReceipt(row.id);
}).then(() => { }).then(() => {

View File

@ -153,12 +153,12 @@
<dict-tag :options="dict.type.approve_status" :value="scope.row.approveStatus"/> <dict-tag :options="dict.type.approve_status" :value="scope.row.approveStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="审批通过时间" align="center" prop="approveTime" width="120"> <!--<el-table-column label="审批通过时间" align="center" prop="approveTime" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ timeProcessing(scope.row.approveTime) }}</span> <span>{{ timeProcessing(scope.row.approveTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="审批节点" align="center" prop="approveNode" width="100" fixed="right" /> <el-table-column label="审批节点" align="center" prop="approveNode" width="100" fixed="right" />-->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width operation-column" width="120" fixed="right"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width operation-column" width="120" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
@ -196,6 +196,7 @@
v-show="scope.row.receiptBillType==='FROM_RECEIVABLE' && scope.row.receiptStatus==='1' && scope.row.approveStatus==='0' " v-show="scope.row.receiptBillType==='FROM_RECEIVABLE' && scope.row.receiptStatus==='1' && scope.row.approveStatus==='0' "
@click="handleReturn(scope.row)" @click="handleReturn(scope.row)"
>退回</el-button> >退回</el-button>
<!-- 撤销按钮已按要求注释
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
@ -203,6 +204,7 @@
v-if="(scope.row.approveStatus === '2' || scope.row.approveStatus==='3') && (scope.row.receiptStatus==='1'||scope.row.receiptStatus==='3')" v-if="(scope.row.approveStatus === '2' || scope.row.approveStatus==='3') && (scope.row.receiptStatus==='1'||scope.row.receiptStatus==='3')"
@click="handleRevoke(scope.row)" @click="handleRevoke(scope.row)"
>撤销</el-button> >撤销</el-button>
-->
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
<el-form-item label="项目编号" prop="projectCode"> <el-form-item v-if="reportDimension === 'project'" label="项目编号" prop="projectCode">
<el-input <el-input
v-model="queryParams.projectCode" v-model="queryParams.projectCode"
placeholder="请输入项目编号" placeholder="请输入项目编号"
@ -9,7 +9,7 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="项目名称" prop="projectName"> <el-form-item v-if="reportDimension === 'project'" label="项目名称" prop="projectName">
<el-input <el-input
v-model="queryParams.projectName" v-model="queryParams.projectName"
placeholder="请输入项目名称" placeholder="请输入项目名称"
@ -17,6 +17,14 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item v-if="reportDimension === 'supplier'" label="供货商" prop="supplier">
<el-input
v-model="queryParams.supplier"
placeholder="请输入供货商"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="计收状态" prop="chargeStatus"> <el-form-item label="计收状态" prop="chargeStatus">
<el-select <el-select
v-model="queryParams.chargeStatus" v-model="queryParams.chargeStatus"
@ -99,6 +107,12 @@
</el-form> </el-form>
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="4">
<el-radio-group v-model="reportDimension" size="mini" @change="handleDimensionChange">
<el-radio-button label="supplier">供货商维度</el-radio-button>
<el-radio-button label="project">项目维度</el-radio-button>
</el-radio-group>
</el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
type="warning" type="warning"
@ -114,10 +128,11 @@
<el-table v-loading="loading" :data="reportList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="reportList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="项目" align="center" prop="orderCode" width="180" v-if="columns.projectCode.visible || columns.projectName.visible" key="orderCode"> <el-table-column v-if="reportDimension === 'project'" label="项目" align="center" prop="orderCode" width="180" key="orderCode">
<el-table-column label="项目编号" align="center" prop="projectCode" width="120" v-if="columns.projectCode.visible" key="receivableWithTax"/> <el-table-column label="项目编号" align="center" prop="projectCode" width="120" v-if="columns.projectCode.visible" key="receivableWithTax"/>
<el-table-column label="项目名称" align="center" prop="projectName" width="120" v-if="columns.projectName.visible" key="receivableWithoutTax"/> <el-table-column label="项目名称" align="center" prop="projectName" width="120" v-if="columns.projectName.visible" key="receivableWithoutTax"/>
</el-table-column> </el-table-column>
<el-table-column v-if="reportDimension === 'supplier'" label="供货商" align="center" prop="supplier" width="180" key="supplier" />
<!-- 应收 --> <!-- 应收 -->
<el-table-column label="应收单" align="center" v-if="columns.receivableWithTax.visible || columns.receivableWithoutTax.visible||columns.receivableTax.visible"> <el-table-column label="应收单" align="center" v-if="columns.receivableWithTax.visible || columns.receivableWithoutTax.visible||columns.receivableTax.visible">
@ -129,16 +144,16 @@
<!-- 毛利 --> <!-- 毛利 -->
<el-table-column label="计收统计" align="center" v-if="columns.chargeStatus.visible || columns.chargedWithoutTax.visible || columns.grossProfit.visible ||columns.grossProfitRate.visible"> <!-- <el-table-column label="计收统计" align="center" v-if="columns.chargeStatus.visible || columns.chargedWithoutTax.visible || columns.grossProfit.visible ||columns.grossProfitRate.visible">-->
<el-table-column label="计收状态" align="center" prop="chargeStatus" width="100" v-if="columns.chargeStatus.visible" key="chargeStatus"> <!-- <el-table-column label="计收状态" align="center" prop="chargeStatus" width="100" v-if="columns.chargeStatus.visible" key="chargeStatus">-->
<template slot-scope="scope"> <!-- <template slot-scope="scope">-->
<dict-tag :options="dict.type.charge_status" :value="scope.row.chargeStatus"/> <!-- <dict-tag :options="dict.type.charge_status" :value="scope.row.chargeStatus"/>-->
</template> <!-- </template>-->
</el-table-column> <!-- </el-table-column>-->
<el-table-column label="已计收未税金额" align="center" prop="chargedWithoutTax" width="120" v-if="columns.chargedWithoutTax.visible" key="chargedWithoutTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/> <!-- <el-table-column label="已计收未税金额" align="center" prop="chargedWithoutTax" width="120" v-if="columns.chargedWithoutTax.visible" key="chargedWithoutTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/>-->
<el-table-column label="毛利" align="center" prop="grossProfit" width="120" v-if="columns.grossProfit.visible" key="grossProfit" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/> <!-- <el-table-column label="毛利" align="center" prop="grossProfit" width="120" v-if="columns.grossProfit.visible" key="grossProfit" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/>-->
<el-table-column label="毛利率" align="center" prop="grossProfitRate" width="100" v-if="columns.grossProfitRate.visible" key="grossProfitRate"/> <!-- <el-table-column label="毛利率" align="center" prop="grossProfitRate" width="100" v-if="columns.grossProfitRate.visible" key="grossProfitRate"/>-->
</el-table-column> <!-- </el-table-column>-->
<!-- <el-table-column label="业务计收时间" align="center" prop="bizChargeDate" width="180" v-if="columns.bizChargeDate.visible" key="bizChargeDate">--> <!-- <el-table-column label="业务计收时间" align="center" prop="bizChargeDate" width="180" v-if="columns.bizChargeDate.visible" key="bizChargeDate">-->
<!-- <template slot-scope="scope">--> <!-- <template slot-scope="scope">-->
@ -243,7 +258,7 @@
</template> </template>
<script> <script>
import { listReport } from "@/api/finance/report"; import { listReport, listSupplierReport } from "@/api/finance/report";
export default { export default {
name: "Report", name: "Report",
@ -264,6 +279,8 @@ export default {
total: 0, total: 0,
// //
reportList: [], reportList: [],
// project-supplier-
reportDimension: "project",
// //
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
@ -271,6 +288,7 @@ export default {
orderCode: null, orderCode: null,
projectCode: null, projectCode: null,
projectName: null, projectName: null,
supplier: null,
chargeStatus: null, chargeStatus: null,
receiptStatus: null, receiptStatus: null,
invoiceStatus: null, invoiceStatus: null,
@ -345,12 +363,21 @@ export default {
/** 查询项目报表列表 */ /** 查询项目报表列表 */
getList() { getList() {
this.loading = true; this.loading = true;
listReport(this.queryParams).then(response => { const requestFn = this.reportDimension === "supplier" ? listSupplierReport : listReport;
requestFn(this.queryParams).then(response => {
this.reportList = response.rows; this.reportList = response.rows;
this.total = response.total; this.total = response.total;
this.loading = false; this.loading = false;
}); });
}, },
/** 维度切换操作 */
handleDimensionChange() {
this.queryParams.pageNum = 1;
this.queryParams.projectCode = null;
this.queryParams.projectName = null;
this.queryParams.supplier = null;
this.getList();
},
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1; this.queryParams.pageNum = 1;

View File

@ -13,7 +13,7 @@
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column> <el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
<el-table-column prop="writeOffAmount" label="本次核销含税总价(元)" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column> <el-table-column prop="writeOffAmount" label="本次核销含税总价(元)" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
<el-table-column prop="vendorName" label="制造商名称" align="center" show-overflow-tooltip></el-table-column> <el-table-column prop="vendorName" label="制造商名称" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="paymentBillCode" label="采购付款单编号" align="center" show-overflow-tooltip></el-table-column> <el-table-column prop="paymentBillCode" label="付款单编号" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="paymentCreateTime" label="付款单生成时间" align="center" width="160"> <el-table-column prop="paymentCreateTime" label="付款单生成时间" align="center" width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.paymentBill.createTime) }}</span> <span>{{ parseTime(scope.row.paymentBill.createTime) }}</span>
@ -32,7 +32,7 @@
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column> <el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
<el-table-column prop="paymentAmount" label="本次核销含税总价(元)" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column> <el-table-column prop="paymentAmount" label="本次核销含税总价(元)" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
<el-table-column prop="vendorName" label="制造商名称" align="center" show-overflow-tooltip></el-table-column> <el-table-column prop="vendorName" label="制造商名称" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="payableBillCode" label="采购应付单编号" align="center" show-overflow-tooltip></el-table-column> <el-table-column prop="payableBillCode" label="应付单编号" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="createTime" label="应付单生成时间" align="center"></el-table-column> <el-table-column prop="createTime" label="应付单生成时间" align="center"></el-table-column>
</el-table> </el-table>
</div> </div>

View File

@ -23,8 +23,8 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="采购应付单编号" prop="payableBillCode"> <el-form-item label="应付单编号" prop="payableBillCode">
<el-input v-model="queryParams.payableBillCode" placeholder="请输入采购应付单编号" clearable <el-input v-model="queryParams.payableBillCode" placeholder="请输入应付单编号" clearable
@keyup.enter.native="handleQuery"/> @keyup.enter.native="handleQuery"/>
</el-form-item> </el-form-item>
<el-form-item label="应付单生成时间"> <el-form-item label="应付单生成时间">
@ -59,8 +59,8 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="采购付款单编号" prop="paymentCode"> <el-form-item label="付款单编号" prop="paymentCode">
<el-input v-model="queryParams.paymentCode" placeholder="请输入采购付款单编号" clearable <el-input v-model="queryParams.paymentCode" placeholder="请输入付款单编号" clearable
@keyup.enter.native="handleQuery"/> @keyup.enter.native="handleQuery"/>
</el-form-item> </el-form-item>
<el-form-item label="付款单生成时间"> <el-form-item label="付款单生成时间">
@ -82,8 +82,8 @@
</el-dialog> </el-dialog>
<div v-if="showTables"> <div v-if="showTables">
<!-- 采购应付单表格 --> <!-- 应付单表格 -->
<h3>采购应付单</h3> <h3>应付单</h3>
<div class="table-summary" style="margin-bottom: 10px;"> <div class="table-summary" style="margin-bottom: 10px;">
<span style="font-weight: bold; margin-right: 20px;">应付单本次核销总额: <span <span style="font-weight: bold; margin-right: 20px;">应付单本次核销总额: <span
style="color: #409EFF">{{ formatCurrency(totalPayableWriteOffAmount.toFixed(2)) }}</span></span> style="color: #409EFF">{{ formatCurrency(totalPayableWriteOffAmount.toFixed(2)) }}</span></span>
@ -144,7 +144,7 @@
<el-table-column label="含税总价(元)" align="center" prop="totalPriceWithTax" width="120" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/> <el-table-column label="含税总价(元)" align="center" prop="totalPriceWithTax" width="120" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/>
<el-table-column label="制造商名称" fixed="right" align="center" prop="vendorName" width="130" <el-table-column label="制造商名称" fixed="right" align="center" prop="vendorName" width="130"
show-overflow-tooltip/> show-overflow-tooltip/>
<el-table-column label="采购应付单编号" fixed="right" align="center" prop="payableBillCode" width="150" <el-table-column label="应付单编号" fixed="right" align="center" prop="payableBillCode" width="150"
show-overflow-tooltip/> show-overflow-tooltip/>
<el-table-column label="生成时间" fixed="right" align="center" prop="createTime" width="120"> <el-table-column label="生成时间" fixed="right" align="center" prop="createTime" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
@ -161,8 +161,8 @@
@pagination="getPayableList" @pagination="getPayableList"
/> />
<!-- 采购付款单表格 --> <!-- 付款单表格 -->
<h3 style="margin-top: 30px;">采购付款单</h3> <h3 style="margin-top: 30px;">付款单</h3>
<div class="table-summary" style="margin-bottom: 10px;"> <div class="table-summary" style="margin-bottom: 10px;">
<span style="font-weight: bold; margin-right: 20px;display: none">付款单本次核销总额: <span <span style="font-weight: bold; margin-right: 20px;display: none">付款单本次核销总额: <span
:style="{color: isWriteOffAmountValid ? '#67C23A' : '#F56C6C'}">{{ :style="{color: isWriteOffAmountValid ? '#67C23A' : '#F56C6C'}">{{
@ -206,7 +206,7 @@
<el-table-column label="含税总价(元)" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/> <el-table-column label="含税总价(元)" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/>
<el-table-column label="制造商名称" fixed="right" align="center" prop="vendorName" width="130" <el-table-column label="制造商名称" fixed="right" align="center" prop="vendorName" width="130"
show-overflow-tooltip/> show-overflow-tooltip/>
<el-table-column label="采购付款单号" fixed="right" align="center" prop="paymentBillCode" width="150" <el-table-column label="付款单号" fixed="right" align="center" prop="paymentBillCode" width="150"
show-overflow-tooltip/> show-overflow-tooltip/>
<el-table-column label="生成时间" fixed="right" align="center" prop="createTime" width="120"> <el-table-column label="生成时间" fixed="right" align="center" prop="createTime" width="120">
<template slot-scope="scope"> <template slot-scope="scope">

View File

@ -9,18 +9,16 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="采购应付单编号" prop="payableBillCode"> <el-form-item label="应付单编号" prop="payableBillCode">
<el-input <el-input v-model="queryParams.payableBillCode"
v-model="queryParams.payableBillCode" placeholder="请输入应付单编号"
placeholder="请输入采购应付单编号"
clearable clearable
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="采购付款单编号" prop="paymentBillCode"> <el-form-item label="付款单编号" prop="paymentBillCode">
<el-input <el-input v-model="queryParams.paymentBillCode"
v-model="queryParams.paymentBillCode" placeholder="请输入付款单编号"
placeholder="请输入采购付款单编号"
clearable clearable
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
@ -85,7 +83,7 @@
<span>{{ timeProcessing(scope.row.createTime) }}</span> <span>{{ timeProcessing(scope.row.createTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="采购付款单编号" align="center" prop="paymentBillCode" /> <el-table-column label="付款单编号" align="center" prop="paymentBillCode" />
<el-table-column label="制造商名称" align="center" prop="vendorName" /> <el-table-column label="制造商名称" align="center" prop="vendorName" />
<el-table-column label="核销类型" align="center" prop="writeOffType"> <el-table-column label="核销类型" align="center" prop="writeOffType">
<template slot-scope="scope"> <template slot-scope="scope">

View File

@ -13,7 +13,7 @@
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column> <el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
<el-table-column prop="writeOffAmount" label="本次核销含税总价(元)" align="center"></el-table-column> <el-table-column prop="writeOffAmount" label="本次核销含税总价(元)" align="center"></el-table-column>
<el-table-column prop="vendorName" label="制造商名称" align="center" show-overflow-tooltip></el-table-column> <el-table-column prop="vendorName" label="制造商名称" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="ticketBillCode" label="采购收票单编号" align="center" show-overflow-tooltip></el-table-column> <el-table-column prop="ticketBillCode" label="收票单编号" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="createTime" label="收票单生成时间" align="center" width="160"> <el-table-column prop="createTime" label="收票单生成时间" align="center" width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.ticketBill.createTime) }}</span> <span>{{ parseTime(scope.row.ticketBill.createTime) }}</span>
@ -33,7 +33,7 @@
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column> <el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
<el-table-column prop="paymentAmount" label="本次核销金额(元)" align="center"></el-table-column> <el-table-column prop="paymentAmount" label="本次核销金额(元)" align="center"></el-table-column>
<el-table-column prop="vendorName" label="制造商名称" align="center"></el-table-column> <el-table-column prop="vendorName" label="制造商名称" align="center"></el-table-column>
<el-table-column prop="payableBillCode" label="采购应付单编号" align="center" show-overflow-tooltip></el-table-column> <el-table-column prop="payableBillCode" label="应付单编号" align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="createTime" label="应付单生成时间" align="center"></el-table-column> <el-table-column prop="createTime" label="应付单生成时间" align="center"></el-table-column>
</el-table> </el-table>
</div> </div>

View File

@ -9,18 +9,16 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="采购应付单编号" prop="payableBillCode"> <el-form-item label="应付单编号" prop="payableBillCode">
<el-input <el-input v-model="queryParams.payableBillCode"
v-model="queryParams.payableBillCode" placeholder="请输入应付单编号"
placeholder="请输入采购应付单编号"
clearable clearable
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="采购收票单编号" prop="ticketBillCode"> <el-form-item label="收票单编号" prop="ticketBillCode">
<el-input <el-input v-model="queryParams.ticketBillCode"
v-model="queryParams.ticketBillCode" placeholder="请输入收票单编号"
placeholder="请输入采购收票单编号"
clearable clearable
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
@ -83,7 +81,7 @@
<span>{{ timeProcessing(scope.row.createTime) }}</span> <span>{{ timeProcessing(scope.row.createTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="采购收票单编号" align="center" prop="ticketBillCode" width="180" /> <el-table-column label="收票单编号" align="center" prop="ticketBillCode" width="180" />
<el-table-column label="制造商名称" align="center" prop="vendorName" width="130" /> <el-table-column label="制造商名称" align="center" prop="vendorName" width="130" />
<el-table-column label="核销类型" align="center" prop="writeOffType" width="120"> <el-table-column label="核销类型" align="center" prop="writeOffType" width="120">
<template slot-scope="scope"> <template slot-scope="scope">

View File

@ -1,5 +1,5 @@
<template> <template>
<el-drawer title="发货单详情" :wrapper-closable="false" :visible.sync="visible" direction="rtl" size="60%" @close="handleClose" append-to-body> <el-drawer title="发货单详情" :wrapper-closable="false" :visible="dialogVisible" @update:visible="handleVisibleChange" 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
@ -100,6 +100,8 @@ export default {
}, },
data() { data() {
return { return {
// visible prop
dialogVisible: false,
// //
snLoading: false, snLoading: false,
// //
@ -112,7 +114,8 @@ export default {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
deliveryId: null, deliveryId: null,
inventoryStatus: '1', // /SNouter_code
inventoryStatus: null,
outerCode: null, outerCode: null,
warehouseId: null, warehouseId: null,
productSnList: [] productSnList: []
@ -120,6 +123,9 @@ export default {
}; };
}, },
watch: { watch: {
visible(val) {
this.dialogVisible = val
},
deliveryId(newVal) { deliveryId(newVal) {
if (newVal) { if (newVal) {
this.handleView(newVal); this.handleView(newVal);
@ -127,6 +133,11 @@ export default {
} }
}, },
methods: { methods: {
// prop
handleVisibleChange(val) {
this.dialogVisible = val
this.$emit('update:visible', val)
},
handleView(id) { handleView(id) {
this.detail = {}; this.detail = {};
this.snList = []; this.snList = [];
@ -135,7 +146,7 @@ export default {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
deliveryId: id, deliveryId: id,
inventoryStatus: '1', inventoryStatus: null,
outerCode: null, outerCode: null,
warehouseId: null, warehouseId: null,
productSnList: [] productSnList: []
@ -143,7 +154,7 @@ export default {
getDelivery(id).then(response => { getDelivery(id).then(response => {
this.detail = response.data; this.detail = response.data;
// Update snQueryParams with data from the detail response // Update snQueryParams with data from the detail response
this.snQueryParams.outerCode = response.data.outerCode; // outer_codeSNouter_code
this.snQueryParams.warehouseId = response.data.warehouseId; this.snQueryParams.warehouseId = response.data.warehouseId;
this.snQueryParams.productSnList = response.data.productSnList; this.snQueryParams.productSnList = response.data.productSnList;
// Fetch the first page of SN list // Fetch the first page of SN list
@ -174,7 +185,7 @@ export default {
}); });
}, },
handleClose() { handleClose() {
this.$emit('update:visible', false); this.handleVisibleChange(false)
}, },
parseTime(time, pattern) { parseTime(time, pattern) {
if (time === undefined || time === null || time === '') { if (time === undefined || time === null || time === '') {

View File

@ -127,6 +127,7 @@ export default {
}, },
form: { form: {
orderCode: null, orderCode: null,
versionCode: null,
productCode: null, productCode: null,
quantity: 0, quantity: 0,
contactAddress: null, contactAddress: null,
@ -149,6 +150,7 @@ export default {
this.reset(); this.reset();
this.product = product; this.product = product;
this.form.orderCode = this.orderInfo.orderCode; this.form.orderCode = this.orderInfo.orderCode;
this.form.versionCode = this.orderInfo.versionCode;
this.form.productCode = product.productCode; this.form.productCode = product.productCode;
this.form.contactAddress = this.orderInfo.notifierAddress; this.form.contactAddress = this.orderInfo.notifierAddress;
this.form.contactPerson = this.orderInfo.notifier; this.form.contactPerson = this.orderInfo.notifier;
@ -184,6 +186,7 @@ export default {
this.outQuantityInfo = { should: 0, submitted: 0 }; this.outQuantityInfo = { should: 0, submitted: 0 };
this.form = { this.form = {
orderCode: null, orderCode: null,
versionCode: null,
productCode: null, productCode: null,
quantity: 0, quantity: 0,
contactAddress: null, contactAddress: null,

View File

@ -34,7 +34,7 @@
<el-button <el-button
size="mini" size="mini"
type="success" type="success"
:disabled="isCheckoutDisabled(scope.row)" :disabled="readOnly || isCheckoutDisabled(scope.row)"
@click="handleCheckout(scope.row)" @click="handleCheckout(scope.row)"
>出库</el-button> >出库</el-button>
</template> </template>
@ -46,28 +46,42 @@
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<span>已生成出库单</span> <span>已生成出库单</span>
</div> </div>
<el-table :data="inventoryOuterList"> <el-tabs v-model="activeOuterVersionTab" type="card" v-if="uniqueOuterVersions.length > 0">
<el-tab-pane
v-for="version in uniqueOuterVersions"
:key="version"
:label="'版本号Rev.' + version"
:name="version"
/>
</el-tabs>
<el-table :data="filteredInventoryOuterList">
<el-table-column label="序号" type="index" width="55" align="center" /> <el-table-column label="序号" type="index" width="55" align="center" />
<el-table-column label="出库单号" prop="outerCode" /> <el-table-column label="出库单号" prop="outerCode" min-width="90" />
<el-table-column label="产品编码" prop="productCode" /> <el-table-column label="产品编码" prop="productCode" min-width="70" />
<el-table-column label="产品型号" prop="model" /> <el-table-column label="产品型号" prop="model" />
<el-table-column label="数量" prop="quantity" /> <el-table-column label="数量" prop="quantity" min-width="45" />
<el-table-column label="出库状态" prop="outerStatus"> <el-table-column label="出库状态" prop="outerStatus" min-width="60">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.outer_outer_status" :value="scope.row.outerStatus"/> <dict-tag :options="dict.type.outer_outer_status" :value="scope.row.outerStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="联系人" prop="contactPerson" /> <el-table-column label="联系人" prop="contactPerson" min-width="60" />
<el-table-column label="收货地址" prop="contactAddress" :show-overflow-tooltip="true" /> <el-table-column label="收货地址" prop="contactAddress" :show-overflow-tooltip="true" />
<el-table-column label="生成时间" prop="createTime" /> <el-table-column label="生成时间" prop="createTime" min-width="70" />
<el-table-column label="操作" align="center" min-width="150"> <el-table-column label="发货状态" prop="deliveryStatus" min-width="70">
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if="scope.row.outerStatus === '1' || scope.row.outerStatus === '4'"> <dict-tag :options="dict.type.outer_delivery_status" :value="scope.row.deliveryStatus"/>
</template>
</el-table-column>
<el-table-column label="操作" align="center" min-width="90">
<template slot-scope="scope">
<div v-if="!readOnly && (scope.row.outerStatus === '1' || scope.row.outerStatus === '4')" class="op-btns">
<el-button size="mini" type="danger" @click="handleDeleteOuter(scope.row)"></el-button> <el-button size="mini" type="danger" @click="handleDeleteOuter(scope.row)"></el-button>
<el-button size="mini" type="default" @click="handleConfirmOuter(scope.row)"></el-button> <el-button size="mini" type="default" @click="handleConfirmOuter(scope.row)"></el-button>
</div> </div>
<div v-else> <div v-else class="op-btns">
<el-button size="mini" type="success" @click="handleViewOuter(scope.row)"></el-button> <el-button size="mini" type="success" @click="handleViewOuter(scope.row)"></el-button>
<el-button size="mini" type="primary" @click="handleViewSn(scope.row)">SN</el-button>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
@ -79,25 +93,33 @@
<checkout-dialog ref="checkoutDialog" :order-info="form" @success="handleCheckoutSuccess"></checkout-dialog> <checkout-dialog ref="checkoutDialog" :order-info="form" @success="handleCheckoutSuccess"></checkout-dialog>
<!-- 出库单详情对话框 --> <!-- 出库单详情对话框 -->
<outer-detail-dialog ref="outerDetailDialog"></outer-detail-dialog> <outer-detail-dialog ref="outerDetailDialog"></outer-detail-dialog>
<!-- 发货记录详情抽屉查看SN码 -->
<delivery-detail :delivery-id="deliveryId" :visible.sync="viewOpen" />
</div> </div>
</template> </template>
<script> <script>
import { getExecution, updateExecution, removeOuter, confirmOuterStatus } from "@/api/inventory/execution"; import { getExecution, updateExecution, removeOuter, confirmOuterStatus } from "@/api/inventory/execution";
import { getDicts } from "@/api/system/dict/data"; import { listDelivery } from "@/api/inventory/delivery";
import CheckoutDialog from './CheckoutDialog.vue'; import CheckoutDialog from './CheckoutDialog.vue';
import OuterDetailDialog from './OuterDetailDialog.vue'; import OuterDetailDialog from './OuterDetailDialog.vue';
import OrderDetailDrawer from "@/views/project/order/OrderDetailDrawer.vue"; import OrderDetailDrawer from "@/views/project/order/OrderDetailDrawer.vue";
import OrderInfo from "@/views/project/order/components/OrderInfoDisplay.vue"; import OrderInfo from "@/views/project/order/components/OrderInfoDisplay.vue";
import DeliveryDetail from "@/views/inventory/delivery/Detail.vue";
export default { export default {
name: "ExecutionEdit", name: "ExecutionEdit",
components: {OrderInfo, OrderDetailDrawer, CheckoutDialog, OuterDetailDialog }, components: {OrderInfo, OrderDetailDrawer, CheckoutDialog, OuterDetailDialog, DeliveryDetail },
dicts: ['bg_type', 'currency_type', 'company_delivery', 'identify_level', 'outer_outer_status'], dicts: ['outer_outer_status', 'outer_delivery_status'],
props: { props: {
orderId: { // Renamed from id to orderId for clarity as it's an order ID orderId: { // Renamed from id to orderId for clarity as it's an order ID
type: [String, Number], type: [String, Number],
required: true required: true
},
// //
readOnly: {
type: Boolean,
default: false
} }
}, },
data() { data() {
@ -118,12 +140,33 @@ export default {
}, },
productDetailList: [], productDetailList: [],
inventoryOuterList: [], inventoryOuterList: [],
industryOptions: [] activeOuterVersionTab: null,
//
deliveryId: null,
viewOpen: false
}; };
}, },
created() { computed: {
if (this.orderId) { //
this.getExecutionDetails(this.orderId); uniqueOuterVersions() {
const list = this.inventoryOuterList || [];
const versions = [...new Set(list
.map(item => item.versionCode)
.filter(v => v !== null && v !== undefined && v !== ''))];
// 使Tab
const orderVersion = this.form && this.form.versionCode;
if (orderVersion !== null && orderVersion !== undefined && orderVersion !== '' && !versions.includes(orderVersion)) {
versions.push(orderVersion);
}
return versions.sort((a, b) => Number(b) - Number(a));
},
//
filteredInventoryOuterList() {
if (!this.inventoryOuterList) return [];
if (this.activeOuterVersionTab === null || this.activeOuterVersionTab === undefined || this.activeOuterVersionTab === '') {
return this.inventoryOuterList;
}
return this.inventoryOuterList.filter(item => String(item.versionCode) === String(this.activeOuterVersionTab));
} }
}, },
watch: { watch: {
@ -134,11 +177,6 @@ export default {
this.getExecutionDetails(newVal); this.getExecutionDetails(newVal);
} }
} }
},
'form.bgProperty'(newVal) {
if(newVal) {
this.fetchIndustryOptions(newVal);
}
} }
}, },
methods: { methods: {
@ -147,19 +185,11 @@ export default {
this.form = response.data.projectOrderInfo; this.form = response.data.projectOrderInfo;
this.productDetailList = response.data.productDetailList; this.productDetailList = response.data.productDetailList;
this.inventoryOuterList = response.data.inventoryOuterList; this.inventoryOuterList = response.data.inventoryOuterList;
this.fetchIndustryOptions(this.form.bgProperty);
this.currentOrderId=this.form.id this.currentOrderId=this.form.id
// 使
this.activeOuterVersionTab = this.form.versionCode ? String(this.form.versionCode) : (this.uniqueOuterVersions.length > 0 ? String(this.uniqueOuterVersions[0]) : null);
}); });
}, },
fetchIndustryOptions(bgType) {
const dictType = bgType === 'YYS' ? 'bg_yys' : 'bg_hysy';
getDicts(dictType).then(response => {
this.industryOptions = response.data.map(item => ({
value: item.dictValue,
label: item.dictLabel
}));
});
},
isCheckoutDisabled(row) { isCheckoutDisabled(row) {
return Number(row.quantity) <= (Number(row.generatedQuantity) + Number(row.confirmQuantity)); return Number(row.quantity) <= (Number(row.generatedQuantity) + Number(row.confirmQuantity));
}, },
@ -183,11 +213,35 @@ export default {
}).then(() => { }).then(() => {
this.getExecutionDetails(this.form.id); this.getExecutionDetails(this.form.id);
this.$modal.msgSuccess("操作成功"); this.$modal.msgSuccess("操作成功");
this.$emit('refresh');
}).catch(() => {}); }).catch(() => {});
}, },
handleViewOuter(row) { handleViewOuter(row) {
this.$refs.outerDetailDialog.show(row.id); this.$refs.outerDetailDialog.show(row.id);
}, },
// SN
handleViewSn(row) {
//
const baseParams = { outerCode: row.outerCode, pageNum: 1, pageSize: 1, orderByColumn: 'createTime', isAsc: 'desc' };
listDelivery(baseParams).then(response => {
const list = response.rows || [];
if (list.length > 0) {
this.deliveryId = list[0].id;
this.viewOpen = true;
return;
}
// delivery_status='1' delivery_status='2'
listDelivery({ ...baseParams, deliveryStatus: '2' }).then(resp => {
const recalledList = resp.rows || [];
if (recalledList.length > 0) {
this.deliveryId = recalledList[0].id;
this.viewOpen = true;
} else {
this.$message.warning('该出库单暂无发货记录');
}
});
});
},
submitForm() { submitForm() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
@ -209,4 +263,13 @@ export default {
.box-card { .box-card {
margin-bottom: 20px; margin-bottom: 20px;
} }
/* 操作列按钮纵向排列:换行 + 边距 + 水平居中 */
.op-btns {
display: flex;
flex-direction: column;
align-items: center;
}
.op-btns .el-button {
margin: 3px 0;
}
</style> </style>

View File

@ -96,7 +96,7 @@
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="executionList" @sort-change="handleSortChange"> <el-table ref="executionTable" v-loading="loading" :data="executionList" @sort-change="handleSortChange">
<el-table-column label="序号" type="index" width="55" align="center" /> <el-table-column label="序号" type="index" width="55" align="center" />
<el-table-column label="项目编号" align="center" prop="projectCode" /> <el-table-column label="项目编号" align="center" prop="projectCode" />
<el-table-column label="合同编号" align="center" prop="orderCode" width="200"> <el-table-column label="合同编号" align="center" prop="orderCode" width="200">
@ -111,7 +111,8 @@
</el-table-column> </el-table-column>
<el-table-column label="备货状态" align="center" prop="orderStockingStatus" width="120"> <el-table-column label="备货状态" align="center" prop="orderStockingStatus" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<span class="stocking-status" :class="getOrderStockingStatusClass(scope.row.orderStockingStatus)" @click="handleShowStockingDetail(scope.row)" style="cursor: pointer;"> <span v-if="scope.row.rebackApproveStatus === '2' || scope.row.orderStatus !== '2'" style="color: red;"></span>
<span v-else class="stocking-status" :class="getOrderStockingStatusClass(scope.row.orderStockingStatus)" @click="handleShowStockingDetail(scope.row)" style="cursor: pointer;">
{{ formatOrderStockingStatus(scope.row.orderStockingStatus) }} {{ formatOrderStockingStatus(scope.row.orderStockingStatus) }}
</span> </span>
</template> </template>
@ -143,13 +144,15 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 发货管理/编辑/查看详情始终显示已撤单为只读查看详情 -->
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
icon="el-icon-edit" :icon="isRecalled(scope.row) ? 'el-icon-view' : 'el-icon-truck'"
@click="handleUpdate(scope.row)" @click="handleUpdate(scope.row)"
v-hasPermi="['inventory:execution:edit']" v-hasPermi="['inventory:execution:edit']"
>编辑</el-button> >{{ isRecalled(scope.row) ? '查看详情' : '编辑' }}</el-button>
<template v-if="scope.row.rebackApproveStatus !== '2' && scope.row.orderStatus === '2'">
<el-button <el-button
v-if="scope.row.signStatus == '0' && scope.row.deliveryStatus=='2'" v-if="scope.row.signStatus == '0' && scope.row.deliveryStatus=='2'"
size="mini" size="mini"
@ -167,6 +170,7 @@
v-hasPermi="['inventory:execution:signdown']" v-hasPermi="['inventory:execution:signdown']"
>签收文件</el-button> >签收文件</el-button>
<el-button <el-button
v-if="scope.row.rebackApproveStatus !== '1'"
size="mini" size="mini"
type="text" type="text"
icon="el-icon-delete" icon="el-icon-delete"
@ -174,6 +178,15 @@
@click="handleRecall(scope.row)" @click="handleRecall(scope.row)"
v-hasPermi="['inventory:execution:recall']" v-hasPermi="['inventory:execution:recall']"
>撤单</el-button> >撤单</el-button>
<el-button
v-if="scope.row.orderStatus === '2' && scope.row.rebackApproveStatus !== '2' && scope.row.rebackApproveStatus !== '0'"
size="mini"
type="text"
icon="el-icon-view"
@click="handleViewRebackApply(scope.row)"
v-hasPermi="['inventory:execution:recall']"
>查看申请</el-button>
</template>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -187,12 +200,14 @@
/> />
<!-- 编辑订单执行对话框 --> <!-- 编辑订单执行对话框 -->
<el-dialog title="编辑订单执行" :close-on-click-modal="false" :visible.sync="editDialogVisible" width="70vw" append-to-body destroy-on-close> <el-dialog :title="currentEditViewOnly ? '查看订单执行详情' : '编辑订单执行'" :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"
:read-only="currentEditViewOnly"
@success="handleEditSuccess" @success="handleEditSuccess"
@cancel="handleEditCancel" @cancel="handleEditCancel"
@refresh="getList"
/> />
<template slot="footer"> <template slot="footer">
<el-button @click="editDialogVisible=false"> </el-button> <el-button @click="editDialogVisible=false"> </el-button>
@ -229,6 +244,15 @@
<!-- 订单详情抽屉 --> <!-- 订单详情抽屉 -->
<order-detail-drawer :visible.sync="orderDrawerVisible" :order-id="currentOrderId" title="订单详情" /> <order-detail-drawer :visible.sync="orderDrawerVisible" :order-id="currentOrderId" title="订单详情" />
<!-- 撤单申请查看弹窗仅查看不审批 -->
<order-reback-detail
:visible.sync="orderRebackApplyVisible"
:order-id="orderRebackApplyOrderId"
:order-code="orderRebackApplyOrderCode"
:process-key="'order_reback'"
:show-approve="false"
/>
<!-- 备货明细弹窗 --> <!-- 备货明细弹窗 -->
<el-dialog :close-on-click-modal="false" :visible.sync="stockingDetailVisible" width="1120px" append-to-body> <el-dialog :close-on-click-modal="false" :visible.sync="stockingDetailVisible" width="1120px" append-to-body>
<span slot="title"> <span slot="title">
@ -469,11 +493,30 @@
</template> </template>
</el-dialog> </el-dialog>
<!-- 提交撤单审批弹窗 -->
<el-dialog title="提交撤单审批" :close-on-click-modal="false" :visible.sync="recallSubmitOpen" width="40%" append-to-body>
<el-form :model="recallSubmitForm" :rules="recallSubmitRules" ref="recallSubmitForm" label-width="120px">
<el-form-item label="金额是否变化" prop="amountChanged">
<el-radio-group v-model="recallSubmitForm.amountChanged">
<el-radio label="是"></el-radio>
<el-radio label="否"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="撤单原因" prop="reason">
<el-input v-model.trim="recallSubmitForm.reason" type="textarea" :rows="3" placeholder="请输入撤单原因" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="handleRecallSubmitCancel"> </el-button>
<el-button type="primary" :loading="recallSubmitting" @click="submitRecallApply"> </el-button>
</span>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { listExecution, recallExecution, downloadSignFile,exportExecution } from "@/api/inventory/execution"; import { listExecution, recallExecutionApply, downloadSignFile,exportExecution } from "@/api/inventory/execution";
import { productMatchList, productMatchBindList, savePurchaseOrderMap, purchaseSnList, bindOrderSnCodes } from "@/api/project/order"; import { productMatchList, productMatchBindList, savePurchaseOrderMap, purchaseSnList, bindOrderSnCodes } from "@/api/project/order";
import { formatCurrency } from "@/utils"; import { formatCurrency } from "@/utils";
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth";
@ -481,6 +524,7 @@ import OrderDetailDrawer from '../../project/order/OrderDetailDrawer.vue';
import ProjectDetailDrawer from '../../project/info/ProjectDetailDrawer.vue'; import ProjectDetailDrawer from '../../project/info/ProjectDetailDrawer.vue';
import Edit from './edit.vue'; import Edit from './edit.vue';
import PurchaseOrderDetail from '../../purchaseorder/components/PurchaseOrderDetail.vue'; import PurchaseOrderDetail from '../../purchaseorder/components/PurchaseOrderDetail.vue';
import OrderRebackDetail from '../../approve/all/components/OrderRebackDetail.vue';
export default { export default {
name: "Execution", name: "Execution",
@ -488,7 +532,8 @@ export default {
ProjectDetailDrawer, ProjectDetailDrawer,
OrderDetailDrawer, OrderDetailDrawer,
Edit, Edit,
PurchaseOrderDetail PurchaseOrderDetail,
OrderRebackDetail
}, },
dicts: ['execution_outer_status', 'execution_delivery_status', 'execution_sign_status', 'purchase_status'], dicts: ['execution_outer_status', 'execution_delivery_status', 'execution_sign_status', 'purchase_status'],
data() { data() {
@ -506,11 +551,25 @@ export default {
// //
editDialogVisible: false, editDialogVisible: false,
currentEditOrderId: null, currentEditOrderId: null,
currentEditViewOnly: false,
// --- --- // --- ---
projectDrawerVisible: false, projectDrawerVisible: false,
orderDrawerVisible: false, orderDrawerVisible: false,
currentProjectId: null, currentProjectId: null,
currentOrderId: null, currentOrderId: null,
// --- ---
orderRebackApplyVisible: false,
orderRebackApplyOrderId: null,
orderRebackApplyOrderCode: '',
// --- ---
recallSubmitOpen: false,
recallSubmitting: false,
recallSubmitOrderId: null,
recallSubmitForm: { amountChanged: '', reason: '' },
recallSubmitRules: {
amountChanged: [{ required: true, message: '请选择金额是否变化', trigger: 'change' }],
reason: [{ required: true, message: '撤单原因不能为空', trigger: 'blur' }]
},
// --- --- // --- ---
stockingDetailVisible: false, stockingDetailVisible: false,
stockingDetailLoading: false, stockingDetailLoading: false,
@ -650,6 +709,27 @@ export default {
this.executionList = response.rows; this.executionList = response.rows;
this.total = response.total; this.total = response.total;
this.loading = false; this.loading = false;
this.syncRowHeight();
});
},
/** 数据行与固定操作列行高同步:对比当前行与操作列行高,取最大值设置实际行高 */
syncRowHeight() {
this.$nextTick(() => {
const tableEl = this.$refs.executionTable && this.$refs.executionTable.$el;
if (!tableEl) return;
const mainRows = tableEl.querySelectorAll('.el-table__body-wrapper > .el-table__body tbody tr');
const fixedRows = tableEl.querySelectorAll('.el-table__fixed-right .el-table__body tbody tr');
mainRows.forEach((row, index) => {
const fixedRow = fixedRows[index];
if (!fixedRow) return;
const mainHeight = row.offsetHeight;
const fixedHeight = fixedRow.offsetHeight;
const maxHeight = Math.max(mainHeight, fixedHeight);
row.style.height = maxHeight + 'px';
fixedRow.style.height = maxHeight + 'px';
row.querySelectorAll('td').forEach(td => { td.style.height = maxHeight + 'px'; });
fixedRow.querySelectorAll('td').forEach(td => { td.style.height = maxHeight + 'px'; });
});
}); });
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
@ -669,11 +749,16 @@ export default {
this.queryParams.isAsc = column.order === 'ascending' ? 'asc' : 'desc'; this.queryParams.isAsc = column.order === 'ascending' ? 'asc' : 'desc';
this.getList(); this.getList();
}, },
/** 编辑按钮操作 */ /** 编辑/查看详情 按钮操作:已撤单为只读查看详情 */
handleUpdate(row) { handleUpdate(row) {
this.currentEditOrderId = row.id; this.currentEditOrderId = row.id;
this.currentEditViewOnly = row.rebackApproveStatus === '2' || row.orderStatus !== '2';
this.editDialogVisible = true; this.editDialogVisible = true;
}, },
/** 是否已撤单(与备货状态列的“已撤单”判断保持一致) */
isRecalled(row) {
return row.rebackApproveStatus === '2' || row.orderStatus !== '2';
},
/** 编辑成功后回调 */ /** 编辑成功后回调 */
handleEditSuccess() { handleEditSuccess() {
this.editDialogVisible = false; this.editDialogVisible = false;
@ -729,14 +814,48 @@ export default {
handleDownloadSign(row) { handleDownloadSign(row) {
window.location.href = process.env.VUE_APP_BASE_API + `/project/order/sign/download?orderId=` + encodeURI(row.id) + '&versionCode=' + encodeURI(row.versionCode); window.location.href = process.env.VUE_APP_BASE_API + `/project/order/sign/download?orderId=` + encodeURI(row.id) + '&versionCode=' + encodeURI(row.versionCode);
}, },
/** 撤单按钮操作 */ /** 撤单按钮操作:提交撤单审批,需填写金额是否变化与撤单原因 */
handleRecall(row) { handleRecall(row) {
this.$modal.confirm('撤回此单后该合同绑定的采购单和SN码信息将同步解除该合同所有出库单以及关联的发货纪录将同步删除操作不可恢复请确认后执行').then(function() { this.recallSubmitOrderId = row.id;
return recallExecution(row.id); this.recallSubmitForm = { amountChanged: '', reason: '' };
}).then(() => { this.recallSubmitOpen = true;
this.getList(); this.$nextTick(() => {
this.$modal.msgSuccess("撤单成功"); this.$refs.recallSubmitForm && this.$refs.recallSubmitForm.clearValidate();
}).catch(() => {}); });
},
/** 关闭提交撤单审批弹窗 */
handleRecallSubmitCancel() {
this.recallSubmitOpen = false;
this.recallSubmitting = false;
},
/** 确认提交撤单审批 */
submitRecallApply() {
this.$refs.recallSubmitForm.validate(valid => {
if (!valid) {
return;
}
const { amountChanged, reason } = this.recallSubmitForm;
this.recallSubmitting = true;
this.$modal.loading();
recallExecutionApply(this.recallSubmitOrderId, reason.trim(), amountChanged)
.then(() => {
this.$modal.closeLoading();
this.$modal.msgSuccess("已提交撤单审批");
this.recallSubmitOpen = false;
this.recallSubmitting = false;
this.getList();
})
.catch(() => {
this.$modal.closeLoading();
this.recallSubmitting = false;
});
});
},
/** 查看撤单申请 */
handleViewRebackApply(row) {
this.orderRebackApplyOrderId = row.id;
this.orderRebackApplyOrderCode = row.orderCode;
this.orderRebackApplyVisible = true;
}, },
/** 查看项目详情 */ /** 查看项目详情 */
handleViewProject(row) { handleViewProject(row) {

View File

@ -62,14 +62,17 @@
<el-table-column label="发货时间" prop="deliveryTime" /> <el-table-column label="发货时间" prop="deliveryTime" />
<el-table-column label="发货数量" prop="quantity" /> <el-table-column label="发货数量" prop="quantity" />
<el-table-column label="发货人" prop="createByName" /> <el-table-column label="发货人" prop="createByName" />
<el-table-column label="操作" align="center"> <el-table-column label="操作" align="center" width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if="scope.row.deliveryStatus === '0'"> <div v-if="scope.row.deliveryStatus === '0'" class="op-btns">
<el-button size="mini" type="danger" @click="handleDeleteDelivery(scope.row.id)"></el-button> <el-button size="mini" type="danger" @click="handleDeleteDelivery(scope.row.id)"></el-button>
<el-button size="mini" type="primary" @click="handleConfirmDelivery(scope.row)"></el-button> <el-button size="mini" type="primary" @click="handleConfirmDelivery(scope.row)"></el-button>
</div> </div>
<div v-else> <div v-else class="op-btns">
<el-button size="mini" type="info" @click="handleViewDelivery(scope.row.id)"></el-button> <el-button size="mini" type="info" @click="handleViewDelivery(scope.row.id)"></el-button>
<!-- 已提交撤回审批可查看申请审批中不可重复提交 -->
<el-button v-if="scope.row.approveStatus" size="mini" type="warning" @click="handleViewRecallApply(scope.row)"></el-button>
<el-button v-if="scope.row.approveStatus !== '1'" size="mini" type="danger" @click="handleRecall(scope.row)" v-hasPermi="['inventory:delivery:recall']"> / </el-button>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
@ -80,6 +83,30 @@
<generate-delivery-form ref="deliveryForm" @success="refreshTables"></generate-delivery-form> <generate-delivery-form ref="deliveryForm" @success="refreshTables"></generate-delivery-form>
<!-- 查看详情弹窗 --> <!-- 查看详情弹窗 -->
<delivery-detail :delivery-id="deliveryId" :visible.sync="viewOpen" /> <delivery-detail :delivery-id="deliveryId" :visible.sync="viewOpen" />
<!-- 撤回审批查看弹窗 -->
<outer-reback-detail
:visible.sync="recallApplyOpen"
:delivery-id="recallApplyDeliveryId"
:outer-code="recallApplyOuterCode"
/>
<!-- 提交出库撤回审批弹窗 -->
<el-dialog title="提交出库撤回审批" :visible.sync="recallSubmitOpen" width="40%" append-to-body :close-on-click-modal="false">
<el-form :model="recallSubmitForm" :rules="recallSubmitRules" ref="recallSubmitForm" label-width="120px">
<el-form-item label="金额是否变化" prop="amountChanged">
<el-radio-group v-model="recallSubmitForm.amountChanged">
<el-radio label="是"></el-radio>
<el-radio label="否"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="撤回原因" prop="reason">
<el-input v-model.trim="recallSubmitForm.reason" type="textarea" :rows="3" placeholder="请输入撤回原因" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="handleRecallSubmitCancel"> </el-button>
<el-button type="primary" :loading="recallSubmitting" @click="submitRecallApply"> </el-button>
</span>
</el-dialog>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button v-if="showReturn && !viewOnly" type="danger" @click="handleStatusChange(form, '4')">退 </el-button> <el-button v-if="showReturn && !viewOnly" type="danger" @click="handleStatusChange(form, '4')">退 </el-button>
@ -90,13 +117,14 @@
<script> <script>
import {changeOuterStatus, getOuter, queryInfo} from '@/api/inventory/outer'; import {changeOuterStatus, getOuter, queryInfo} from '@/api/inventory/outer';
import { removeDelivery, updateDeliveryStatus } from '@/api/inventory/delivery'; import { removeDelivery, updateDeliveryStatus, recallDelivery, recallApply } from '@/api/inventory/delivery';
import GenerateDeliveryForm from './GenerateDeliveryForm.vue'; import GenerateDeliveryForm from './GenerateDeliveryForm.vue';
import DeliveryDetail from '@/views/inventory/delivery/Detail.vue'; import DeliveryDetail from '@/views/inventory/delivery/Detail.vue';
import OuterRebackDetail from '@/views/approve/all/components/OuterRebackDetail.vue';
export default { export default {
name: "OuterForm", name: "OuterForm",
components: { GenerateDeliveryForm, DeliveryDetail }, components: { GenerateDeliveryForm, DeliveryDetail, OuterRebackDetail },
props: { props: {
viewOnly: { viewOnly: {
type: Boolean, type: Boolean,
@ -113,6 +141,21 @@ export default {
deliveryList: [], deliveryList: [],
deliveryId: null, deliveryId: null,
viewOpen: false, viewOpen: false,
recallApplyOpen: false,
recallApplyDeliveryId: null,
recallApplyOuterCode: '',
//
recallSubmitOpen: false,
recallSubmitting: false,
recallSubmitDeliveryId: null,
recallSubmitForm: {
amountChanged: '',
reason: ''
},
recallSubmitRules: {
amountChanged: [{ required: true, message: '请选择金额是否变化', trigger: 'change' }],
reason: [{ required: true, message: '撤回原因不能为空', trigger: 'blur' }]
},
}; };
}, },
methods: { methods: {
@ -123,7 +166,6 @@ 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;
@ -140,12 +182,23 @@ export default {
this.deliveryList = []; this.deliveryList = [];
this.deliveryId = null; this.deliveryId = null;
this.viewOpen = false; this.viewOpen = false;
this.recallApplyOpen = false;
this.recallApplyDeliveryId = null;
this.recallApplyOuterCode = '';
this.recallSubmitOpen = false;
this.recallSubmitting = false;
this.recallSubmitDeliveryId = null;
this.recallSubmitForm = { amountChanged: '', reason: '' };
if (this.$refs.recallSubmitForm) {
this.$refs.recallSubmitForm.clearValidate();
}
}, },
// //
refreshTables() { refreshTables() {
queryInfo(this.form.id).then(res => { queryInfo(this.form.id).then(res => {
this.productList = res.data.productVoList || []; this.productList = res.data.productVoList || [];
this.deliveryList = res.data.deliveryList || []; this.deliveryList = res.data.deliveryList || [];
this.showReturn = this.deliveryList.length <= 0;
}); });
}, },
// //
@ -159,15 +212,15 @@ export default {
}; };
this.$refs.deliveryForm.open(row, formData); this.$refs.deliveryForm.open(row, formData);
}, },
// //
handleDeleteDelivery(deliveryId) { handleDeleteDelivery(deliveryId) {
this.$confirm('确定撤销该发货记录吗?', '提示', { this.$confirm('确定取消该发货记录吗取消后SN码将恢复为未出库状态请确认', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
removeDelivery(deliveryId).then(() => { removeDelivery(deliveryId).then(() => {
this.$message.success('撤销成功'); this.$message.success('取消发货成功');
this.refreshTables(); this.refreshTables();
}); });
}).catch(() => {}); }).catch(() => {});
@ -188,6 +241,7 @@ export default {
updateDeliveryStatus(data).then(() => { updateDeliveryStatus(data).then(() => {
this.$message.success('确认成功'); this.$message.success('确认成功');
this.refreshTables(); this.refreshTables();
this.$emit('success');
}); });
}).catch(() => {}); }).catch(() => {});
}, },
@ -196,6 +250,83 @@ export default {
this.deliveryId = deliveryId; this.deliveryId = deliveryId;
this.viewOpen = true; this.viewOpen = true;
}, },
//
handleViewRecallApply(row) {
this.recallApplyDeliveryId = row.id;
this.recallApplyOuterCode = row.outerCode;
this.recallApplyOpen = true;
},
// /
handleRecall(row) {
if (this.isToday(row.createTime)) {
//
this.handleRecallDelivery(row);
} else {
//
this.handleRecallNotToday(row);
}
},
//
isToday(dateStr) {
if (!dateStr) return false;
const date = new Date(dateStr);
if (isNaN(date.getTime())) return false;
const today = new Date();
return date.getFullYear() === today.getFullYear() &&
date.getMonth() === today.getMonth() &&
date.getDate() === today.getDate();
},
//
handleRecallNotToday(row) {
this.recallSubmitDeliveryId = row.id;
this.recallSubmitForm = { amountChanged: '', reason: '' };
this.recallSubmitOpen = true;
this.$nextTick(() => {
this.$refs.recallSubmitForm && this.$refs.recallSubmitForm.clearValidate();
});
},
//
handleRecallSubmitCancel() {
this.recallSubmitOpen = false;
this.recallSubmitting = false;
},
//
submitRecallApply() {
this.$refs.recallSubmitForm.validate(valid => {
if (!valid) {
return;
}
const { amountChanged, reason } = this.recallSubmitForm;
this.recallSubmitting = true;
this.$modal.loading();
recallApply(this.recallSubmitDeliveryId, reason.trim(), amountChanged)
.then(() => {
this.$modal.closeLoading();
this.$message.success('已提交出库撤回审批');
this.recallSubmitOpen = false;
this.recallSubmitting = false;
this.refreshTables();
})
.catch(() => {
this.$modal.closeLoading();
this.recallSubmitting = false;
});
});
},
// /
handleRecallDelivery(row) {
const id = row.id;
this.$confirm('撤回 / 作废 该发货记录后无法恢复,操作不可逆转,确认无误后再执行!', "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
return recallDelivery(id);
}).then(() => {
this.$message.success("撤回 / 作废 成功");
this.refreshTables();
}).catch(() => {});
},
handleStatusChange(row, status) { handleStatusChange(row, status) {
const actionText = status === '3' ? '确认接收' : '退回'; const actionText = status === '3' ? '确认接收' : '退回';
this.$confirm(`确认要"${actionText}"该出库单吗?`, '系统提示', { this.$confirm(`确认要"${actionText}"该出库单吗?`, '系统提示', {
@ -231,4 +362,13 @@ export default {
color: #c0c4cc; color: #c0c4cc;
cursor: not-allowed; cursor: not-allowed;
} }
/* 操作列按钮纵向排列:换行 + 边距 + 水平居中 */
.op-btns {
display: flex;
flex-direction: column;
align-items: center;
}
.op-btns .el-button {
margin: 3px 0;
}
</style> </style>

View File

@ -64,7 +64,8 @@
<template slot-scope="scope"> <template slot-scope="scope">
<!-- <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)"></el-button>--> <!-- <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)"></el-button>-->
<template v-if="scope.row.outerStatus === '3'"> <template v-if="scope.row.outerStatus === '3'">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['inventory:outer:edit']"></el-button> <el-button size="mini" type="text" icon="el-icon-truck" @click="handleUpdate(scope.row)" v-hasPermi="['inventory:outer:edit']"></el-button>
<el-button size="mini" type="text" icon="el-icon-document" @click="handleDeliveryRecord(scope.row)" v-if="scope.row.deliveryStatus === '1' || scope.row.deliveryStatus === '2'"></el-button>
</template> </template>
<template v-else> <template v-else>
<el-button size="mini" type="text" style="color: red" @click="handleStatusChange(scope.row, '4')">退回</el-button> <el-button size="mini" type="text" style="color: red" @click="handleStatusChange(scope.row, '4')">退回</el-button>
@ -82,17 +83,22 @@
<!-- 详情抽屉 --> <!-- 详情抽屉 -->
<outer-details ref="details"></outer-details> <outer-details ref="details"></outer-details>
<!-- 发货记录详情抽屉 -->
<delivery-detail :delivery-id="deliveryId" :visible.sync="viewOpen" />
</div> </div>
</template> </template>
<script> <script>
import { listOuter, exportOuter, changeOuterStatus } from '@/api/inventory/outer'; import { listOuter, exportOuter, changeOuterStatus } from '@/api/inventory/outer';
import { listDelivery } from '@/api/inventory/delivery';
import OuterForm from './components/OuterForm.vue'; import OuterForm from './components/OuterForm.vue';
import OuterDetails from './components/OuterDetails.vue'; import OuterDetails from './components/OuterDetails.vue';
import DeliveryDetail from '@/views/inventory/delivery/Detail.vue';
export default { export default {
name: "Outer", name: "Outer",
components: { OuterForm, OuterDetails }, components: { OuterForm, OuterDetails, DeliveryDetail },
dicts: ['outer_delivery_status'], dicts: ['outer_delivery_status'],
data() { data() {
return { return {
@ -113,6 +119,9 @@ export default {
isAsc : 'desc', isAsc : 'desc',
orderByColumn : 'createTime', orderByColumn : 'createTime',
}, },
//
deliveryId: null,
viewOpen: false,
}; };
}, },
created() { created() {
@ -149,6 +158,29 @@ export default {
handleUpdate(row) { handleUpdate(row) {
this.$refs.form.open(row.id); this.$refs.form.open(row.id);
}, },
//
handleDeliveryRecord(row) {
//
const baseParams = { outerCode: row.outerCode, pageNum: 1, pageSize: 1, orderByColumn: 'createTime', isAsc: 'desc' };
listDelivery(baseParams).then(response => {
const list = response.rows || [];
if (list.length > 0) {
this.deliveryId = list[0].id;
this.viewOpen = true;
return;
}
// delivery_status='1' delivery_status='2'
listDelivery({ ...baseParams, deliveryStatus: '2' }).then(resp => {
const recalledList = resp.rows || [];
if (recalledList.length > 0) {
this.deliveryId = recalledList[0].id;
this.viewOpen = true;
} else {
this.$message.warning('该出库单暂无发货记录');
}
});
});
},
handleStatusChange(row, status) { handleStatusChange(row, status) {
const actionText = status === '3' ? '确认接收' : '退回'; const actionText = status === '3' ? '确认接收' : '退回';
this.$confirm(`确认要"${actionText}"该出库单吗?`, '系统提示', { this.$confirm(`确认要"${actionText}"该出库单吗?`, '系统提示', {

View File

@ -267,7 +267,9 @@ export default {
return this.orderId != null; return this.orderId != null;
}, },
isOrderApprovedOrInReview() { isOrderApprovedOrInReview() {
return this.form.orderStatus === '1' || this.form.orderStatus === '2'; // orderStatus=2 rebackApproveStatus=2/
const isRebackApproved = this.form.orderStatus === '2' && this.form.rebackApproveStatus === '2';
return !isRebackApproved && (this.form.orderStatus === '1' || this.form.orderStatus === '2');
}, },
uniqueVersions() { uniqueVersions() {
if (!this.approveLogList || this.approveLogList.length === 0) return []; if (!this.approveLogList || this.approveLogList.length === 0) return [];
@ -483,6 +485,7 @@ export default {
return; return;
} }
this.form.orderStatus = '0'; this.form.orderStatus = '0';
this.form.rebackApproveStatus = null;
this._performSubmit(); this._performSubmit();
}, },
submitForApproval() { submitForApproval() {
@ -500,6 +503,7 @@ export default {
this.form.processTemplate = data.processTemplate; this.form.processTemplate = data.processTemplate;
this.form.processType = data.processType; this.form.processType = data.processType;
this.form.orderStatus = '1'; this.form.orderStatus = '1';
this.form.rebackApproveStatus = null;
this._performSubmit(true); this._performSubmit(true);
}, },
handleSelectProject() { handleSelectProject() {

View File

@ -95,7 +95,8 @@
</el-table-column> </el-table-column>
<el-table-column label="订单状态" align="center" prop="orderStatus" width="100"> <el-table-column label="订单状态" align="center" prop="orderStatus" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.order_status" :value="scope.row.orderStatus"/> <span v-if="scope.row.orderStatus === '2' && scope.row.rebackApproveStatus === '2'" style="color: red;"></span>
<dict-tag v-else :options="dict.type.order_status" :value="scope.row.orderStatus"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="代表处" align="center" prop="agentName" width="100" :show-overflow-tooltip="true"/> <el-table-column label="代表处" align="center" prop="agentName" width="100" :show-overflow-tooltip="true"/>

View File

@ -87,7 +87,7 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="入库仓" prop="warehouseId"> <el-form-item label="入库仓" prop="warehouseId">
<span>{{ selectedVendor.warehouseName }}</span> <span>{{ form.warehouseName }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">

View File

@ -71,4 +71,4 @@ unis:
enabled: false enabled: false
opportunity: opportunity:
integration: integration:
base-url: http://10.100.52.24:8080 base-url: http://192.168.2.158:8080

View File

@ -153,6 +153,8 @@ process:
financeReceiptRefound: finance_receipt_refound financeReceiptRefound: finance_receipt_refound
financeInvoiceApprove: finance_invoice_approve financeInvoiceApprove: finance_invoice_approve
financeInvoiceRefound: finance_invoice_refound financeInvoiceRefound: finance_invoice_refound
outerReback: outer_reback
orderReback: order_reback
#业务执行实例bean name ,可以按审批节点配置 业务审批回调方法处理业务逻辑. key 为流程节点主键ID value 要执行的业务方法名称,不配置则默认调用TodoCommonTemplate.todoApproveCallback #业务执行实例bean name ,可以按审批节点配置 业务审批回调方法处理业务逻辑. key 为流程节点主键ID value 要执行的业务方法名称,不配置则默认调用TodoCommonTemplate.todoApproveCallback
instance: instance:
@ -178,6 +180,10 @@ process:
beanName: omsTicketBillServiceImpl beanName: omsTicketBillServiceImpl
financeTicketRefound: financeTicketRefound:
beanName: omsTicketBillServiceImpl beanName: omsTicketBillServiceImpl
outerReback:
beanName: inventoryDeliveryServiceImpl
orderReback:
beanName: executionTrackServiceImpl
unis: unis:
inventory: inventory:
allAuthRole: 103,101 allAuthRole: 103,101

View File

@ -113,6 +113,14 @@
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId> <artifactId>hutool-extra</artifactId>
</dependency> </dependency>
<!-- javax.mail:hutool-extra中mail模块的编译期间接依赖hutool将其声明为optional不会传递需在此显式引入
否则Eclipse(JDT)编译器会报The type javax.mail.internet.MimeMessage cannot be resolved
并在class中植入 Unresolved compilation problem 运行时Error -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.6</version>
</dependency>
<dependency> <dependency>
<groupId>org.thymeleaf</groupId> <groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId> <artifactId>thymeleaf</artifactId>

View File

@ -21,5 +21,7 @@ public class Definition {
private String financeReceiptRefound; private String financeReceiptRefound;
private String financeInvoiceApprove; private String financeInvoiceApprove;
private String financeInvoiceRefound; private String financeInvoiceRefound;
private String outerReback;
private String orderReback;
} }

View File

@ -23,6 +23,9 @@ public class Instance {
private Map<String, Object> finance_receipt_refound; private Map<String, Object> finance_receipt_refound;
private Map<String, Object> finance_invoice_approve; private Map<String, Object> finance_invoice_approve;
private Map<String, Object> finance_invoice_refound; private Map<String, Object> finance_invoice_refound;
private Map<String, Object> outer_reback;
/** 撤单审批 */
private Map<String, Object> order_reback;
} }

View File

@ -35,6 +35,14 @@ public class DataProcessController extends BaseController {
dataProcessService.inventoryInnerGeneratePayableBill(innerId); dataProcessService.inventoryInnerGeneratePayableBill(innerId);
} }
//按发货单生成应付单(规则同确认发货:出库付款供应商、取入库价、不重复生成)
@Anonymous
@GetMapping("/generatePayableBillByDeliveryId")
public AjaxResult generatePayableBillByDeliveryId(@RequestParam("deliveryId") Long deliveryId) {
String payableBillCode = dataProcessService.generatePayableBillByDeliveryId(deliveryId);
return AjaxResult.success("应付单生成成功,应付单号:" + payableBillCode);
}
@PostMapping("/projectTransfer") @PostMapping("/projectTransfer")
public AjaxResult projectTransfer(@RequestBody ProjectTransferRequest request) { public AjaxResult projectTransfer(@RequestBody ProjectTransferRequest request) {
return dataProcessService.projectTransfer(request); return dataProcessService.projectTransfer(request);

View File

@ -56,6 +56,19 @@ public class OmsFinanceOperateReportController extends BaseController
return getDataTable(list); return getDataTable(list);
} }
/**
*
*/
@RequiresPermissions("sip:financeReport:list")
@PostMapping("/listSupplier")
@ResponseBody
public TableDataInfo listSupplier(OmsFinanceOperateReport omsFinanceOperateReport)
{
startPage();
List<OmsFinanceOperateReport> list = omsFinanceOperateReportService.selectOmsFinanceOperateReportSupplierList(omsFinanceOperateReport);
return getDataTable(list);
}
/** /**
* *
*/ */
@ -70,6 +83,20 @@ public class OmsFinanceOperateReportController extends BaseController
return util.exportExcel(list, "财务模块报数据"); return util.exportExcel(list, "财务模块报数据");
} }
/**
*
*/
@RequiresPermissions("sip:financeReport:export")
@Log(title = "财务模块报", businessType = BusinessType.EXPORT)
@PostMapping("/exportSupplier")
@ResponseBody
public AjaxResult exportSupplier(OmsFinanceOperateReport omsFinanceOperateReport)
{
List<OmsFinanceOperateReport> list = omsFinanceOperateReportService.selectOmsFinanceOperateReportSupplierList(omsFinanceOperateReport);
ExcelUtil<OmsFinanceOperateReport> util = new ExcelUtil<OmsFinanceOperateReport>(OmsFinanceOperateReport.class);
return util.exportExcel(list, "财务模块报数据");
}
/** /**
* *
*/ */

View File

@ -129,6 +129,7 @@ public class ProjectOrderInfoController extends BaseController
result.put("user", ShiroUtils.getSysUser()); result.put("user", ShiroUtils.getSysUser());
Todo todo = new Todo(); Todo todo = new Todo();
todo.setBusinessKey(projectOrderInfo.getOrderCode()); todo.setBusinessKey(projectOrderInfo.getOrderCode());
todo.setProcessKeyList(Arrays.asList(processConfig.getDefinition().getOrderApproveOffline(), processConfig.getDefinition().getOrderApproveOnline()));
result.put("approveLog", todoService.selectTodoCompletedList(todo)); result.put("approveLog", todoService.selectTodoCompletedList(todo));
todo.setApproveUser(ShiroUtils.getUserId().toString()); todo.setApproveUser(ShiroUtils.getUserId().toString());
result.put("todo", todoService.selectTodo(todo)); result.put("todo", todoService.selectTodo(todo));

View File

@ -4,6 +4,7 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.sip.domain.ApprovalTask; import com.ruoyi.sip.domain.ApprovalTask;
import com.ruoyi.sip.domain.TodoConfirm;
import com.ruoyi.sip.service.IApprovalTaskService; import com.ruoyi.sip.service.IApprovalTaskService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -43,4 +44,18 @@ public class VueApprovalTaskController extends BaseController {
return AjaxResult.success(approvalTaskService.selectApprovalTaskCount()); return AjaxResult.success(approvalTaskService.selectApprovalTaskCount());
} }
/**
*
*
* @param todoConfirm
* @return
*/
@PostMapping("/confirm")
public AjaxResult addConfirm(@RequestBody TodoConfirm todoConfirm) {
if (todoConfirm.getProcessInstanceId() == null && todoConfirm.getBusinessKey() == null) {
return AjaxResult.error("流程实例ID和业务主键不能同时为空");
}
return toAjax(approvalTaskService.insertTodoConfirm(todoConfirm));
}
} }

View File

@ -5,6 +5,7 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.sip.domain.InventoryDelivery; import com.ruoyi.sip.domain.InventoryDelivery;
import com.ruoyi.sip.domain.OmsInventoryDeliveryDetail; import com.ruoyi.sip.domain.OmsInventoryDeliveryDetail;
@ -19,6 +20,7 @@ import cn.hutool.core.collection.CollUtil;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -46,7 +48,10 @@ public class VueDeliveryController extends BaseController {
@RequiresPermissions("inventory:delivery:list") @RequiresPermissions("inventory:delivery:list")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(InventoryDelivery inventoryDelivery) { public TableDataInfo list(InventoryDelivery inventoryDelivery) {
inventoryDelivery.setDeliveryStatus(InventoryDelivery.DeliveryStatusEnum.CONFIRM_DELIVERY.getCode()); // 默认只查已发货,前端显式指定状态时按指定状态查询
if (StringUtils.isEmpty(inventoryDelivery.getDeliveryStatus())) {
inventoryDelivery.setDeliveryStatus(InventoryDelivery.DeliveryStatusEnum.CONFIRM_DELIVERY.getCode());
}
if (!inventoryAuthService.authAll()) { if (!inventoryAuthService.authAll()) {
List<String> productCodeList = inventoryAuthService.authProductCode(); List<String> productCodeList = inventoryAuthService.authProductCode();
if (CollUtil.isEmpty(productCodeList)) { if (CollUtil.isEmpty(productCodeList)) {
@ -115,6 +120,19 @@ public class VueDeliveryController extends BaseController {
return AjaxResult.success(); return AjaxResult.success();
} }
/**
*
*/
@RequiresPermissions("inventory:delivery:recall")
@Log(title = "发货记录", businessType = BusinessType.UPDATE)
@PostMapping("/recall/apply")
public AjaxResult recallApply(@RequestBody Map<String, Object> params) {
inventoryDeliveryService.applyRecall(Long.valueOf(params.get("id").toString()),
String.valueOf(params.get("reason")),
String.valueOf(params.get("amountChanged")));
return AjaxResult.success();
}
/** /**
* *
*/ */

View File

@ -21,6 +21,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Controller (Vue) * Controller (Vue)
@ -111,6 +112,20 @@ public class VueInventoryExecutionController extends BaseController
return AjaxResult.success(); return AjaxResult.success();
} }
/**
*
*/
@RequiresPermissions("inventory:execution:recall")
@PostMapping("/recall/apply")
@Log(title = "执行单撤单审批", businessType = BusinessType.UPDATE)
public AjaxResult recallApply(@RequestBody Map<String, Object> params)
{
inventoryExecutionService.applyRecall(Long.valueOf(params.get("id").toString()),
String.valueOf(params.get("reason")),
String.valueOf(params.get("amountChanged")));
return AjaxResult.success();
}
/** /**
* *
*/ */

View File

@ -19,6 +19,9 @@ import com.ruoyi.sip.service.IOmsWarehouseInfoService;
import com.ruoyi.sip.service.IProductInfoService; import com.ruoyi.sip.service.IProductInfoService;
import com.ruoyi.sip.service.IOmsPurchaseOrderService; import com.ruoyi.sip.service.IOmsPurchaseOrderService;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.sql.SqlUtil;
import com.ruoyi.sip.domain.OmsInventoryInner; import com.ruoyi.sip.domain.OmsInventoryInner;
import com.ruoyi.sip.service.IOmsInventoryInnerService; import com.ruoyi.sip.service.IOmsInventoryInnerService;
import com.ruoyi.sip.domain.InventoryOuter; import com.ruoyi.sip.domain.InventoryOuter;
@ -151,6 +154,11 @@ public class VueInventoryInfoController extends BaseController {
} }
info.setProductCodeList(productCodeList); info.setProductCodeList(productCodeList);
} }
// 与列表查询保持一致,应用排序规则
String orderBy = buildOrderBy(info);
if (StringUtils.isNotEmpty(orderBy)) {
PageHelper.orderBy(orderBy);
}
List<ProductInfo> list = productInfoService.listInventory(info); List<ProductInfo> list = productInfoService.listInventory(info);
ExcelUtil<ProductInfo> util = new ExcelUtil<>(ProductInfo.class); ExcelUtil<ProductInfo> util = new ExcelUtil<>(ProductInfo.class);
return util.exportExcel(list, "产品库存数据"); return util.exportExcel(list, "产品库存数据");
@ -231,4 +239,16 @@ public class VueInventoryInfoController extends BaseController {
List<ProductInventoryInnerDTO> list = omsInventoryInnerService.listInventoryInner(query); List<ProductInventoryInnerDTO> list = omsInventoryInnerService.listInventoryInner(query);
return getDataTable(list); return getDataTable(list);
} }
/**
* orderByColumn + isAsc
*/
private String buildOrderBy(ProductInfo info) {
String orderByColumn = info.getOrderByColumn();
if (StringUtils.isEmpty(orderByColumn)) {
return "";
}
String isAsc = info.getIsAsc();
return SqlUtil.escapeOrderBySql(orderByColumn + " " + (StringUtils.isEmpty(isAsc) ? "" : isAsc));
}
} }

View File

@ -50,6 +50,7 @@ public class VueInventoryOuterController extends BaseController
{ {
inventoryOuter.setOuterStatusList(Arrays.asList(InventoryOuter.OuterStatusEnum.WAIT_RECEIVE.getCode(), InventoryOuter.OuterStatusEnum.RECEIVED.getCode())); inventoryOuter.setOuterStatusList(Arrays.asList(InventoryOuter.OuterStatusEnum.WAIT_RECEIVE.getCode(), InventoryOuter.OuterStatusEnum.RECEIVED.getCode()));
inventoryOuter.setExcludeRecalled(true);
if (!inventoryAuthService.authAll()){ if (!inventoryAuthService.authAll()){
List<String> productCodeList = inventoryAuthService.authProductCode(); List<String> productCodeList = inventoryAuthService.authProductCode();
if (CollUtil.isEmpty(productCodeList)){ if (CollUtil.isEmpty(productCodeList)){

View File

@ -94,7 +94,12 @@ public class VueProjectOrderInfoController extends BaseController {
mmap.put("projectOrderInfo", projectOrderInfo); mmap.put("projectOrderInfo", projectOrderInfo);
mmap.put("user", ShiroUtils.getSysUser()); mmap.put("user", ShiroUtils.getSysUser());
//是否可修改文件 //是否可修改文件
mmap.put("canUpdate", ProjectOrderInfo.OrderStatus.WAIT_COMMIT.getCode().equals(projectOrderInfo.getOrderStatus()) ||ProjectOrderInfo.OrderStatus.APPROVE_REJECT.getCode().equals(projectOrderInfo.getOrderStatus())); boolean rebackApproved = ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode().equals(projectOrderInfo.getOrderStatus())
&& "2".equals(projectOrderInfo.getRebackApproveStatus());
mmap.put("canUpdate", ProjectOrderInfo.OrderStatus.WAIT_COMMIT.getCode().equals(projectOrderInfo.getOrderStatus())
|| ProjectOrderInfo.OrderStatus.APPROVE_REJECT.getCode().equals(projectOrderInfo.getOrderStatus())
// 撤单审批通过后允许重新编辑上传文件
|| rebackApproved);
// boolean showFileFlag=!ProjectOrderInfo.OrderStatus.WAIT_COMMIT.getCode().equals(projectOrderInfo.getOrderStatus()) // boolean showFileFlag=!ProjectOrderInfo.OrderStatus.WAIT_COMMIT.getCode().equals(projectOrderInfo.getOrderStatus())
// && !ProjectOrderInfo.OrderStatus.APPROVE_REJECT.getCode().equals(projectOrderInfo.getOrderStatus()) // && !ProjectOrderInfo.OrderStatus.APPROVE_REJECT.getCode().equals(projectOrderInfo.getOrderStatus())
// && !"1".equals(projectOrderInfo.getProcessTemplate()); // && !"1".equals(projectOrderInfo.getProcessTemplate());
@ -119,8 +124,6 @@ public class VueProjectOrderInfoController extends BaseController {
mmap.put("uploadFinalFile", (ShiroUtils.getSubject().hasRole("business") || ShiroUtils.getSysUser().isAdmin()) && mmap.put("uploadFinalFile", (ShiroUtils.getSubject().hasRole("business") || ShiroUtils.getSysUser().isAdmin()) &&
ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode().equals(projectOrderInfo.getOrderStatus())); ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode().equals(projectOrderInfo.getOrderStatus()));
mmap.put("todo", todoService.selectTodo(todo)); mmap.put("todo", todoService.selectTodo(todo));
return AjaxResult.success(mmap); return AjaxResult.success(mmap);
} }

View File

@ -40,6 +40,15 @@ public class ApprovalTask extends BaseEntity {
/** 审批人 */ /** 审批人 */
private String approveUser; private String approveUser;
/** 审批人姓名集合 */
private String approveUserNames;
/** 流程实例ID */
private String processInstanceId;
/** 是否确认 */
private Boolean confirm;
/** 业务主键 */ /** 业务主键 */
private String businessKey; private String businessKey;
@ -55,4 +64,7 @@ public class ApprovalTask extends BaseEntity {
/** 审批状态1-待处理 / 2-已通过 / 3-已驳回) */ /** 审批状态1-待处理 / 2-已通过 / 3-已驳回) */
private String approveStatus; private String approveStatus;
/** 财务角色是否可见全部财务类审批单 */
private Boolean financeView;
} }

View File

@ -75,6 +75,8 @@ public class InventoryDelivery extends BaseEntity
private String deliveryStatus; private String deliveryStatus;
/** 撤回审批状态1-撤回审批中2-撤回审批完成3-撤回已驳回 */
private String approveStatus;
private List<String> productSnList; private List<String> productSnList;
private List<InventoryInfo> productSnDataList; private List<InventoryInfo> productSnDataList;
@ -87,6 +89,9 @@ public class InventoryDelivery extends BaseEntity
private String remark; private String remark;
private Long itemId; private Long itemId;
/** 版本号 */
private String versionCode;
@Getter @Getter

View File

@ -67,6 +67,8 @@ public class InventoryOuter extends BaseEntity
@Excel(name = "发货状态",dictType = "outer_delivery_status") @Excel(name = "发货状态",dictType = "outer_delivery_status")
private String deliveryStatus; private String deliveryStatus;
/** 查询条件是否排除已撤回delivery_status=3的数据 */
private boolean excludeRecalled;
/** 联系人 */ /** 联系人 */
// @Excel(name = "联系人") // @Excel(name = "联系人")
private String contactPerson; private String contactPerson;
@ -89,6 +91,7 @@ public class InventoryOuter extends BaseEntity
private String deliveryTimeType; private String deliveryTimeType;
private Long warehouseId; private Long warehouseId;
private String receivableBillCode; private String receivableBillCode;
private String versionCode;
private List<InventoryOuterDetail> detailList; private List<InventoryOuterDetail> detailList;
@ -120,9 +123,9 @@ public class InventoryOuter extends BaseEntity
/** 已确认 */ /** 已确认 */
PART_DELIVERY("1", "部分发货"), PART_DELIVERY("1", "部分发货"),
ALL_DELIVERY("2", "全部发货"), ALL_DELIVERY("2", "全部发货"),
/** 已撤回 */
REBACK("3", "已撤回");
;
private final String code; private final String code;
private final String desc; private final String desc;
DeliveryStatusEnum(String code, String desc) { DeliveryStatusEnum(String code, String desc) {

View File

@ -29,6 +29,8 @@ public class OmsFinanceOperateReport extends BaseEntity
private String orderCode; private String orderCode;
private String projectCode; private String projectCode;
private String projectName; private String projectName;
@Excel(name = "供应商名称")
private String supplier;
/** 应收含税总价 */ /** 应收含税总价 */
@Excel(name = "应收含税总价") @Excel(name = "应收含税总价")
@ -43,29 +45,29 @@ public class OmsFinanceOperateReport extends BaseEntity
private BigDecimal receivableTax; private BigDecimal receivableTax;
/** 计收状态 */ /** 计收状态 */
@Excel(name = "计收状态") // @Excel(name = "计收状态")
private String chargeStatus; private String chargeStatus;
/** 已计收未税金额 */ /** 已计收未税金额 */
@Excel(name = "已计收未税金额") // @Excel(name = "已计收未税金额")
private BigDecimal chargedWithoutTax; private BigDecimal chargedWithoutTax;
/** 毛利 */ /** 毛利 */
@Excel(name = "毛利") // @Excel(name = "毛利")
private BigDecimal grossProfit; private BigDecimal grossProfit;
/** 毛利率 */ /** 毛利率 */
@Excel(name = "毛利率") // @Excel(name = "毛利率")
private BigDecimal grossProfitRate; private BigDecimal grossProfitRate;
/** 业务计收时间 */ /** 业务计收时间 */
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Excel(name = "业务计收时间", width = 30, dateFormat = "yyyy-MM-dd") // @Excel(name = "业务计收时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date bizChargeDate; private Date bizChargeDate;
/** 财务计收时间 */ /** 财务计收时间 */
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Excel(name = "财务计收时间", width = 30, dateFormat = "yyyy-MM-dd") // @Excel(name = "财务计收时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date financeChargeDate; private Date financeChargeDate;
/** 收款状态 */ /** 收款状态 */
@ -242,7 +244,7 @@ public class OmsFinanceOperateReport extends BaseEntity
/** 数据快照日期 */ /** 数据快照日期 */
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Excel(name = "数据快照日期", width = 30, dateFormat = "yyyy-MM-dd") // @Excel(name = "数据快照日期", width = 30, dateFormat = "yyyy-MM-dd")
private Date dataDate; private Date dataDate;
@Getter @Getter

View File

@ -93,6 +93,7 @@ public class OmsReceivableBill extends BaseEntity
private BigDecimal uninvoicedAmount; private BigDecimal uninvoicedAmount;
private String projectName; private String projectName;
private String projectCode; private String projectCode;
private List<OmsReceivableReceiptDetail> detailList; private List<OmsReceivableReceiptDetail> detailList;
private List<OmsReceivableInvoiceDetail> invoiceDetailList; private List<OmsReceivableInvoiceDetail> invoiceDetailList;

View File

@ -297,6 +297,11 @@ public class ProjectOrderInfo extends BaseEntity {
// 财务归档状态 0:未完结 1:已完结 // 财务归档状态 0:未完结 1:已完结
private String financeStatus; private String financeStatus;
/**
* ApproveStatusEnum1- 2- 3-
*/
private String rebackApproveStatus;
private List<ProjectOrderFileLog> contractFileList; private List<ProjectOrderFileLog> contractFileList;
private List<ProjectOrderFileLog> configFileList; private List<ProjectOrderFileLog> configFileList;
private Map<String, List<ProjectOrderFileLog>> contractTableData; private Map<String, List<ProjectOrderFileLog>> contractTableData;

View File

@ -0,0 +1,42 @@
package com.ruoyi.sip.domain;
import lombok.Data;
import lombok.ToString;
import com.ruoyi.common.core.domain.BaseEntity;
import java.util.Date;
/**
* bu_todo_confirm
*
* @author auto
* @date 2026-08-21
*/
@Data
@ToString
public class TodoConfirm extends BaseEntity {
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 流程实例ID */
private String processInstanceId;
/** 业务主键 */
private String businessKey;
/** 流程类型 */
private String processKey;
/** 确认人ID */
private String userId;
/** 确认人姓名 */
private String userName;
/** 确认时间 */
private Date createTime;
}

View File

@ -72,6 +72,15 @@ public class TodoController extends BaseController {
return AjaxResult.success(todoService.selectTodoCompletedList(todo)); return AjaxResult.success(todoService.selectTodoCompletedList(todo));
} }
/**
*
*/
@PostMapping("/todo/apply-list")
@ResponseBody
public AjaxResult applyList(@RequestBody Todo todo) {
return AjaxResult.success(todoService.selectTodoList(todo));
}
/** /**
* *
*/ */

View File

@ -75,6 +75,10 @@ public class Todo extends BaseEntity
private String extendField2; private String extendField2;
/** 扩展字段3 */
private String extendField3;
private String taskId; private String taskId;
private String processInstanceId; private String processInstanceId;

View File

@ -161,6 +161,8 @@ public class ProcessListener extends AbstractFlowableEngineEventListener {
.setApproveUserName(userService.selectUserById(Long.valueOf(taskEntity.getAssignee())).getUserName()) .setApproveUserName(userService.selectUserById(Long.valueOf(taskEntity.getAssignee())).getUserName())
.setApproveUser(taskEntity.getAssignee()) .setApproveUser(taskEntity.getAssignee())
.setExtendField1(ObjectUtils.isNotEmpty(processVariables.get("extendField1"))?(String) processVariables.get("extendField1"):null) .setExtendField1(ObjectUtils.isNotEmpty(processVariables.get("extendField1"))?(String) processVariables.get("extendField1"):null)
.setExtendField2(ObjectUtils.isNotEmpty(processVariables.get("extendField2"))?String.valueOf(processVariables.get("extendField2")):null)
.setExtendField3(ObjectUtils.isNotEmpty(processVariables.get("extendField3"))?String.valueOf(processVariables.get("extendField3")):null)
.setTaskId(taskEntity.getId()) .setTaskId(taskEntity.getId())
.setProcessInstanceId(taskEntity.getProcessInstanceId()) .setProcessInstanceId(taskEntity.getProcessInstanceId())
.setFormKey(taskEntity.getFormKey())); .setFormKey(taskEntity.getFormKey()));

View File

@ -70,6 +70,14 @@ public interface TodoMapper
Todo selectTodoCompleted(Todo todo); Todo selectTodoCompleted(Todo todo);
/**
* id
*
* @param processInstanceId id
* @return
*/
Todo selectFirstCompletedByProcessInstanceId(@Param("processInstanceId") String processInstanceId);
Todo selectTodo(Todo todo); Todo selectTodo(Todo todo);
List<Todo> selectGQOrYQCompletedList(Todo todo); List<Todo> selectGQOrYQCompletedList(Todo todo);

View File

@ -1,6 +1,7 @@
package com.ruoyi.sip.mapper; package com.ruoyi.sip.mapper;
import com.ruoyi.sip.domain.ApprovalTask; import com.ruoyi.sip.domain.ApprovalTask;
import com.ruoyi.sip.domain.TodoConfirm;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@ -27,5 +28,13 @@ public interface ApprovalTaskMapper {
* *
* @return * @return
*/ */
Map<String, Integer> selectApprovalTaskCount(@Param("approveUser") String approveUser); Map<String, Integer> selectApprovalTaskCount(@Param("approveUser") String approveUser, @Param("financeView") Boolean financeView);
/**
*
*
* @param todoConfirm
* @return
*/
int insertTodoConfirm(TodoConfirm todoConfirm);
} }

View File

@ -91,4 +91,6 @@ public interface InventoryInfoMapper
int countByOrderCodeAndPurchaseNo(@Param("orderCode") String orderCode, @Param("purchaseNo") String purchaseNo, @Param("productCode") String productCode); int countByOrderCodeAndPurchaseNo(@Param("orderCode") String orderCode, @Param("purchaseNo") String purchaseNo, @Param("productCode") String productCode);
void clearOrderCodeByIds(@Param("idList") List<Long> idList); void clearOrderCodeByIds(@Param("idList") List<Long> idList);
void clearPayableBillCodeByIds(@Param("idList") List<Long> idList);
} }

View File

@ -4,6 +4,7 @@ import java.math.BigDecimal;
import java.util.List; import java.util.List;
import com.ruoyi.sip.domain.InventoryOuter; import com.ruoyi.sip.domain.InventoryOuter;
import com.ruoyi.sip.domain.VendorInfo; import com.ruoyi.sip.domain.VendorInfo;
import org.apache.ibatis.annotations.Param;
/** /**
* Mapper * Mapper
@ -71,4 +72,13 @@ public interface InventoryOuterMapper
BigDecimal selectOutPriceByCode(String outerCode); BigDecimal selectOutPriceByCode(String outerCode);
List<InventoryOuter> listByInvoiceBillCode(String invoiceBillCode); List<InventoryOuter> listByInvoiceBillCode(String invoiceBillCode);
/**
*
*
* @param outerCode
* @param deliveryStatus
* @return
*/
int updateDeliveryStatusByOuterCode(@Param("outerCode") String outerCode, @Param("deliveryStatus") String deliveryStatus);
} }

View File

@ -29,6 +29,14 @@ public interface OmsFinanceOperateReportMapper
*/ */
public List<OmsFinanceOperateReport> selectOmsFinanceOperateReportList(OmsFinanceOperateReport omsFinanceOperateReport); public List<OmsFinanceOperateReport> selectOmsFinanceOperateReportList(OmsFinanceOperateReport omsFinanceOperateReport);
/**
*
*
* @param omsFinanceOperateReport
* @return
*/
public List<OmsFinanceOperateReport> selectOmsFinanceOperateReportSupplierList(OmsFinanceOperateReport omsFinanceOperateReport);
/** /**
* *
* *

View File

@ -56,6 +56,14 @@ public interface ProjectOrderInfoMapper
*/ */
public int updateProjectOrderInfo(ProjectOrderInfo projectOrderInfo); public int updateProjectOrderInfo(ProjectOrderInfo projectOrderInfo);
/**
*
*
* @param id
* @return
*/
public int clearRebackApproveStatus(Long id);
/** /**
* *
* *

View File

@ -1,6 +1,7 @@
package com.ruoyi.sip.service; package com.ruoyi.sip.service;
import com.ruoyi.sip.domain.ApprovalTask; import com.ruoyi.sip.domain.ApprovalTask;
import com.ruoyi.sip.domain.TodoConfirm;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -28,4 +29,12 @@ public interface IApprovalTaskService {
*/ */
Map<String, Integer> selectApprovalTaskCount(); Map<String, Integer> selectApprovalTaskCount();
/**
*
*
* @param todoConfirm
* @return
*/
int insertTodoConfirm(TodoConfirm todoConfirm);
} }

View File

@ -7,6 +7,14 @@ public interface IDataProcessService {
void inventoryInnerGeneratePayableBill(Long innerId); void inventoryInnerGeneratePayableBill(Long innerId);
/**
*
*
* @param deliveryId ID
* @return
*/
String generatePayableBillByDeliveryId(Long deliveryId);
AjaxResult projectTransfer(ProjectTransferRequest request); AjaxResult projectTransfer(ProjectTransferRequest request);
void generateServiceBillsWhenAllDelivered(String orderCode); void generateServiceBillsWhenAllDelivered(String orderCode);

View File

@ -26,4 +26,13 @@ public interface IExecutionTrackService {
List<ProductWarehouseInfo> checkOutPreview(String productCode, Integer quantity); List<ProductWarehouseInfo> checkOutPreview(String productCode, Integer quantity);
void recall(Long id); void recall(Long id);
/**
*
*
* @param id
* @param reason
* @param amountChanged
*/
void applyRecall(Long id, String reason, String amountChanged);
} }

View File

@ -70,6 +70,24 @@ public interface IInventoryDeliveryService
void recall(Long id); void recall(Long id);
/**
*
*
* @param id
* @param reason
* @param amountChanged
*/
void applyRecall(Long id, String reason, String amountChanged);
/**
*
*
* @param deliveryId
* @param outerCode /
* @param skipReceivablePayable
*/
void handleRecallReceivablePayable(Long deliveryId, String outerCode, boolean skipReceivablePayable);
List<InventoryDeliveryDetailExcelDto> detailExport(InventoryDelivery inventoryDelivery); List<InventoryDeliveryDetailExcelDto> detailExport(InventoryDelivery inventoryDelivery);
void generateServiceBillsWhenAllDelivered(String orderCode); void generateServiceBillsWhenAllDelivered(String orderCode);

View File

@ -80,6 +80,8 @@ public interface IInventoryInfoService
void clearOutInfo(List<Long> collect); void clearOutInfo(List<Long> collect);
void clearPayableBillCodeByIds(List<Long> idList);
List<String> checkUnq(List<String> productSnList); List<String> checkUnq(List<String> productSnList);
void deleteInventoryInfoByInnerIds(String[] idArray); void deleteInventoryInfoByInnerIds(String[] idArray);

View File

@ -28,6 +28,14 @@ public interface IOmsFinanceOperateReportService
*/ */
public List<OmsFinanceOperateReport> selectOmsFinanceOperateReportList(OmsFinanceOperateReport omsFinanceOperateReport); public List<OmsFinanceOperateReport> selectOmsFinanceOperateReportList(OmsFinanceOperateReport omsFinanceOperateReport);
/**
*
*
* @param omsFinanceOperateReport
* @return
*/
public List<OmsFinanceOperateReport> selectOmsFinanceOperateReportSupplierList(OmsFinanceOperateReport omsFinanceOperateReport);
/** /**
* *
* *

View File

@ -1,7 +1,10 @@
package com.ruoyi.sip.service.impl; package com.ruoyi.sip.service.impl;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.sip.domain.ApprovalTask; import com.ruoyi.sip.domain.ApprovalTask;
import com.ruoyi.sip.domain.TodoConfirm;
import com.ruoyi.sip.mapper.ApprovalTaskMapper; import com.ruoyi.sip.mapper.ApprovalTaskMapper;
import com.ruoyi.sip.service.IApprovalTaskService; import com.ruoyi.sip.service.IApprovalTaskService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -31,6 +34,7 @@ public class ApprovalTaskServiceImpl implements IApprovalTaskService {
@Override @Override
public List<ApprovalTask> selectApprovalTaskList(ApprovalTask approvalTask) { public List<ApprovalTask> selectApprovalTaskList(ApprovalTask approvalTask) {
approvalTask.setApproveUser(String.valueOf(ShiroUtils.getUserId())); approvalTask.setApproveUser(String.valueOf(ShiroUtils.getUserId()));
approvalTask.setFinanceView(isFinanceRole());
List<ApprovalTask> list = approvalTaskMapper.selectApprovalTaskList(approvalTask); List<ApprovalTask> list = approvalTaskMapper.selectApprovalTaskList(approvalTask);
return list; return list;
} }
@ -42,7 +46,37 @@ public class ApprovalTaskServiceImpl implements IApprovalTaskService {
*/ */
@Override @Override
public Map<String, Integer> selectApprovalTaskCount() { public Map<String, Integer> selectApprovalTaskCount() {
return approvalTaskMapper.selectApprovalTaskCount(String.valueOf(ShiroUtils.getUserId())); return approvalTaskMapper.selectApprovalTaskCount(String.valueOf(ShiroUtils.getUserId()), isFinanceRole());
}
/**
*
*
* @param todoConfirm
* @return
*/
@Override
public int insertTodoConfirm(TodoConfirm todoConfirm) {
SysUser sysUser = ShiroUtils.getSysUser();
// 没有用户信息时直接返回,不写入确认记录
if (sysUser == null) {
return 0;
}
todoConfirm.setUserId(String.valueOf(sysUser.getUserId()));
todoConfirm.setUserName(sysUser.getUserName());
return approvalTaskMapper.insertTodoConfirm(todoConfirm);
}
/**
* "财务"
*/
private boolean isFinanceRole() {
SysUser user = ShiroUtils.getSysUser();
if (user == null || user.getRoles() == null || user.getRoles().isEmpty()) {
return false;
}
return user.getRoles().stream()
.anyMatch(role -> StringUtils.isNotEmpty(role.getRoleName())
&& role.getRoleName().contains("财务"));
} }
} }

View File

@ -49,9 +49,15 @@ public class DataProcessServiceImpl implements IDataProcessService {
@Resource @Resource
private OmsInventoryInnerMapper omsInventoryInnerMapper; private OmsInventoryInnerMapper omsInventoryInnerMapper;
@Resource
private InventoryDeliveryMapper inventoryDeliveryMapper;
@Resource @Resource
private InventoryInfoMapper inventoryInfoMapper; private InventoryInfoMapper inventoryInfoMapper;
@Resource
private IInventoryInfoService inventoryInfoService;
@Resource @Resource
private IProductInfoService productInfoService; private IProductInfoService productInfoService;
@ -145,6 +151,54 @@ public class DataProcessServiceImpl implements IDataProcessService {
payableBillService.insertOmsPayableBill(payableBill, vendorInfo.getPayConfigDay()); payableBillService.insertOmsPayableBill(payableBill, vendorInfo.getPayConfigDay());
} }
@Override
public String generatePayableBillByDeliveryId(Long deliveryId) {
if (deliveryId == null) {
throw new ServiceException("deliveryId不能为空");
}
bindShiroUser(1L, "admin", "平台管理员");
InventoryDelivery inventoryDelivery = inventoryDeliveryMapper.selectInventoryDeliveryById(deliveryId);
if (inventoryDelivery == null) {
throw new ServiceException("发货记录不存在");
}
List<ProductInfo> productInfos = productInfoService.selectProductInfoByCodeList(Collections.singletonList(inventoryDelivery.getProductCode()));
if (CollUtil.isEmpty(productInfos)) {
throw new ServiceException("未找到对应产品");
}
ProductInfo productInfo = productInfos.get(0);
//生成应付单 取入库价 规则同确认发货:库存明细未生成过应付单的不重复生成
VendorInfo vendorInfo = vendorInfoService.selectVendorInfoByVendorCode(productInfo.getVendorCode());
List<InventoryInfo> inventoryInfos = inventoryInfoService.listByDeliveryId(deliveryId);
//生成过应付单的不用再次生成
inventoryInfos = inventoryInfos.stream().filter(item -> StringUtils.isEmpty(item.getPayableBillCode())).collect(Collectors.toList());
if (CollUtil.isEmpty(inventoryInfos)) {
throw new ServiceException("该发货单已生成过应付单或无可生成应付单的库存明细");
}
OmsPayableBill payableBill = new OmsPayableBill();
payableBill.setProductCode(productInfo.getProductCode());
payableBill.setProductType(productInfo.getType());
payableBill.setVendorCode(productInfo.getVendorCode());
payableBill.setInventoryCode(inventoryDelivery.getOuterCode());
BigDecimal allPrice = inventoryInfos.stream().map(InventoryInfo::getInnerPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
payableBill.setTotalPriceWithTax(allPrice);
BigDecimal defaultTaxRate = new BigDecimal(defaultTax);
BigDecimal allPriceWithOutTax = inventoryInfos.stream().map(item ->
{
BigDecimal taxRate = item.getTaxRate() == null ? defaultTaxRate : item.getTaxRate();
return item.getInnerPrice().divide(BigDecimal.ONE.add(taxRate), 2, RoundingMode.HALF_UP);
})
.reduce(BigDecimal.ZERO, BigDecimal::add);
payableBill.setTaxRate(inventoryInfos.get(0).getTaxRate() == null ? defaultTaxRate : inventoryInfos.get(0).getTaxRate());
payableBill.setTotalPriceWithoutTax(allPriceWithOutTax);
payableBill.setTaxAmount(allPrice.subtract(payableBill.getTotalPriceWithoutTax()));
payableBill.setOrderCode(inventoryDelivery.getOrderCode());
payableBillService.insertOmsPayableBill(payableBill, vendorInfo == null ? 0 : vendorInfo.getPayConfigDay());
//回写应付单号,防止重复生成
List<InventoryInfo> saveList = inventoryInfos.stream().peek(item -> item.setPayableBillCode(payableBill.getPayableBillCode())).collect(Collectors.toList());
inventoryInfoService.saveBatch(saveList);
return payableBill.getPayableBillCode();
}
private void bindShiroUser(Long userId, String loginName, String userName) { private void bindShiroUser(Long userId, String loginName, String userName) {
SecurityManager securityManager = new DefaultSecurityManager(); SecurityManager securityManager = new DefaultSecurityManager();
SecurityUtils.setSecurityManager(securityManager); SecurityUtils.setSecurityManager(securityManager);

View File

@ -2,21 +2,27 @@ package com.ruoyi.sip.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.config.flow.ProcessConfig;
import com.ruoyi.common.enums.ApproveStatusEnum;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.sip.domain.*; import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.dto.inventory.ProductDetail; import com.ruoyi.sip.dto.inventory.ProductDetail;
import com.ruoyi.sip.dto.inventory.ProductWarehouseInfo; import com.ruoyi.sip.dto.inventory.ProductWarehouseInfo;
import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.flowable.mapper.TodoMapper;
import com.ruoyi.sip.flowable.service.TodoCommonTemplate;
import com.ruoyi.sip.flowable.service.TodoService; import com.ruoyi.sip.flowable.service.TodoService;
import com.ruoyi.sip.mapper.InventoryDeliveryMapper; import com.ruoyi.sip.mapper.InventoryDeliveryMapper;
import com.ruoyi.sip.mapper.InventoryInfoMapper; import com.ruoyi.sip.mapper.InventoryInfoMapper;
import com.ruoyi.sip.mapper.InventoryOuterMapper;
import com.ruoyi.sip.mapper.OmsPurchaseOrderMapMapper; import com.ruoyi.sip.mapper.OmsPurchaseOrderMapMapper;
import com.ruoyi.sip.mapper.ProjectOrderInfoMapper; import com.ruoyi.sip.mapper.ProjectOrderInfoMapper;
import com.ruoyi.sip.service.*; import com.ruoyi.sip.service.*;
import com.ruoyi.sip.vo.DeliveryApproveVo;
import com.ruoyi.sip.vo.ExecutionOrderVo; import com.ruoyi.sip.vo.ExecutionOrderVo;
import org.apache.commons.collections.CollectionUtils; import org.flowable.engine.runtime.ProcessInstance;
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 org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -40,10 +46,12 @@ import java.util.stream.Collectors;
* 2025/08/08 ch 1.0 Why & What is modified: <> * * 2025/08/08 ch 1.0 Why & What is modified: <> *
*/ */
@Service @Service
public class ExecutionTrackServiceImpl implements IExecutionTrackService { public class ExecutionTrackServiceImpl implements IExecutionTrackService, TodoCommonTemplate {
@Resource @Resource
private ProjectOrderInfoMapper projectOrderInfoMapper; private ProjectOrderInfoMapper projectOrderInfoMapper;
@Autowired @Autowired
private IProjectOrderInfoService projectOrderInfoService;
@Autowired
private IProjectProductInfoService projectProductInfoService; private IProjectProductInfoService projectProductInfoService;
@Autowired @Autowired
private IInventoryInfoService inventoryInfoService; private IInventoryInfoService inventoryInfoService;
@ -60,8 +68,12 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
@Autowired @Autowired
private InventoryInfoMapper inventoryInfoMapper; private InventoryInfoMapper inventoryInfoMapper;
@Autowired @Autowired
private InventoryOuterMapper inventoryOuterMapper;
@Autowired
private TodoService todoService; private TodoService todoService;
@Autowired @Autowired
private TodoMapper todoMapper;
@Autowired
private IProjectProductInfoBakService projectProductInfoBakService; private IProjectProductInfoBakService projectProductInfoBakService;
@Autowired @Autowired
private IProjectOrderInfoRecallService projectOrderInfoRecallService; private IProjectOrderInfoRecallService projectOrderInfoRecallService;
@ -69,6 +81,10 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
private OmsPurchaseOrderMapMapper omsPurchaseOrderMapMapper; private OmsPurchaseOrderMapMapper omsPurchaseOrderMapMapper;
@Autowired @Autowired
private IInventoryOuterDetailService inventoryOuterDetailService; private IInventoryOuterDetailService inventoryOuterDetailService;
@Autowired
private IInventoryDeliveryService inventoryDeliveryService;
@Autowired
private ProcessConfig processConfig;
@Override @Override
public ExecutionOrderVo selectInfo(Long id) { public ExecutionOrderVo selectInfo(Long id) {
ExecutionOrderVo vo = new ExecutionOrderVo(); ExecutionOrderVo vo = new ExecutionOrderVo();
@ -148,15 +164,19 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
productDetails.forEach(detail -> { productDetails.forEach(detail -> {
List<InventoryOuter> outers = outersByProductCode.get(detail.getProductCode()); List<InventoryOuter> outers = outersByProductCode.get(detail.getProductCode());
if (outers != null) { if (outers != null) {
// 已撤回delivery_status=3的出库单不参与统计
List<InventoryOuter> activeOuters = outers.stream()
.filter(outer -> !InventoryOuter.DeliveryStatusEnum.REBACK.getCode().equals(outer.getDeliveryStatus()))
.collect(Collectors.toList());
// generatedQuantity: 状态为"已生成"(假设为"1")的出库单数量总和 // generatedQuantity: 状态为"已生成"(假设为"1")的出库单数量总和
Long generated = outers.stream() Long generated = activeOuters.stream()
.filter(outer -> !InventoryOuter.OuterStatusEnum.WAIT_RECEIVE.getCode().equals(outer.getOuterStatus()) .filter(outer -> !InventoryOuter.OuterStatusEnum.WAIT_RECEIVE.getCode().equals(outer.getOuterStatus())
&& !InventoryOuter.OuterStatusEnum.RECEIVED.getCode().equals(outer.getOuterStatus())) && !InventoryOuter.OuterStatusEnum.RECEIVED.getCode().equals(outer.getOuterStatus()))
.mapToLong(InventoryOuter::getQuantity) .mapToLong(InventoryOuter::getQuantity)
.sum(); .sum();
// confirmQuantity: 状态为"已确认"(假设为"2")的出库单数量总和 // confirmQuantity: 状态为"已确认"(假设为"2")的出库单数量总和
Long confirmed = outers.stream() Long confirmed = activeOuters.stream()
.filter(outer -> InventoryOuter.OuterStatusEnum.WAIT_RECEIVE.getCode().equals(outer.getOuterStatus()) .filter(outer -> InventoryOuter.OuterStatusEnum.WAIT_RECEIVE.getCode().equals(outer.getOuterStatus())
||InventoryOuter.OuterStatusEnum.RECEIVED.getCode().equals(outer.getOuterStatus())) ||InventoryOuter.OuterStatusEnum.RECEIVED.getCode().equals(outer.getOuterStatus()))
.mapToLong(InventoryOuter::getQuantity) .mapToLong(InventoryOuter::getQuantity)
@ -251,13 +271,30 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void recall(Long id) { public void recall(Long id) {
recall(id, ShiroUtils.getUserId().toString());
}
/**
*
*
* @param id
* @param updateBy id
*/
@Transactional(rollbackFor = Exception.class)
public void recall(Long id, String updateBy) {
recall(id, updateBy, true);
}
/**
*
*
* @param id
* @param updateBy id
* @param resetOrderStatus
*/
@Transactional(rollbackFor = Exception.class)
public void recall(Long id, String updateBy, boolean resetOrderStatus) {
List<InventoryDelivery> inventoryDeliveryList = projectOrderInfoMapper.selectInentoryDeliveryByProjectOrderInfoId(id); List<InventoryDelivery> inventoryDeliveryList = projectOrderInfoMapper.selectInentoryDeliveryByProjectOrderInfoId(id);
for (InventoryDelivery inventoryDelivery : inventoryDeliveryList) {
List<DeliveryApproveVo> deliveryApproveVoList = deliveryMapper.selectDeliveryApproveList(inventoryDelivery.getId());
if (CollectionUtils.isNotEmpty(deliveryApproveVoList)) {
throw new ServiceException("存在已完成或审批中的应收、应付信息,无法执行撤回操作");
}
}
//查询订单 //查询订单
ProjectOrderInfo projectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoById(id); ProjectOrderInfo projectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoById(id);
@ -269,7 +306,9 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
updateOrder.setDeliveryStatus(ProjectOrderInfo.DeliveryStatusEnum.NOT_DELIVERY.getCode()); updateOrder.setDeliveryStatus(ProjectOrderInfo.DeliveryStatusEnum.NOT_DELIVERY.getCode());
updateOrder.setSignStatus(ProjectOrderInfo.SignStatusEnum.NOT_SIGN.getCode()); updateOrder.setSignStatus(ProjectOrderInfo.SignStatusEnum.NOT_SIGN.getCode());
updateOrder.setVersionCode(String.valueOf(Integer.parseInt(projectOrderInfo.getVersionCode())+1)); updateOrder.setVersionCode(String.valueOf(Integer.parseInt(projectOrderInfo.getVersionCode())+1));
updateOrder.setOrderStatus(ProjectOrderInfo.OrderStatus.APPROVE_REJECT.getCode()); if (resetOrderStatus) {
updateOrder.setOrderStatus(ProjectOrderInfo.OrderStatus.APPROVE_REJECT.getCode());
}
updateOrder.setActualPurchaseAmount(projectOrderInfo.getShipmentAmount()); updateOrder.setActualPurchaseAmount(projectOrderInfo.getShipmentAmount());
updateOrder.setOrderStockingStatus(ProjectOrderInfo.OrderStockingStatusEnum.PHZ.getCode()); updateOrder.setOrderStockingStatus(ProjectOrderInfo.OrderStockingStatusEnum.PHZ.getCode());
updateOrder.setUpdateTime(new Date()); updateOrder.setUpdateTime(new Date());
@ -280,7 +319,7 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
projectOrderInfoRecall.setOrderCode(projectOrderInfo.getOrderCode()); projectOrderInfoRecall.setOrderCode(projectOrderInfo.getOrderCode());
projectOrderInfoRecall.setVersionCode(Integer.parseInt(projectOrderInfo.getVersionCode())); projectOrderInfoRecall.setVersionCode(Integer.parseInt(projectOrderInfo.getVersionCode()));
projectOrderInfoRecall.setOperationVersion(projectOrderInfo.getOperationVersion()); projectOrderInfoRecall.setOperationVersion(projectOrderInfo.getOperationVersion());
projectOrderInfoRecall.setCreateBy(ShiroUtils.getUserId().toString()); projectOrderInfoRecall.setCreateBy(updateBy);
projectOrderInfoRecallService.insertProjectOrderInfoRecall(projectOrderInfoRecall); projectOrderInfoRecallService.insertProjectOrderInfoRecall(projectOrderInfoRecall);
//剔除流程 //剔除流程
todoService.deleteTodoByBusinessKey(projectOrderInfo.getOrderCode()); todoService.deleteTodoByBusinessKey(projectOrderInfo.getOrderCode());
@ -307,16 +346,15 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
deliveryMapper.updateInventoryDelivery(updateDelivery); deliveryMapper.updateInventoryDelivery(updateDelivery);
} }
} }
//修改库存 //作废出库单delivery_status=3不物理删除出库单及明细参考发货撤回处理
InventoryOuter inventoryOuter = new InventoryOuter(); InventoryOuter inventoryOuter = new InventoryOuter();
inventoryOuter.setOrderCode(projectOrderInfo.getOrderCode()); inventoryOuter.setOrderCode(projectOrderInfo.getOrderCode());
List<InventoryOuter> inventoryOuters = outerService.selectInventoryOuterList(inventoryOuter); List<InventoryOuter> inventoryOuters = outerService.selectInventoryOuterList(inventoryOuter);
if (CollUtil.isNotEmpty(inventoryOuters)) { if (CollUtil.isNotEmpty(inventoryOuters)) {
List<String> outerCodeList = inventoryOuters.stream() for (InventoryOuter outer : inventoryOuters) {
.map(InventoryOuter::getOuterCode) inventoryOuterMapper.updateDeliveryStatusByOuterCode(outer.getOuterCode(),
.collect(Collectors.toList()); InventoryOuter.DeliveryStatusEnum.REBACK.getCode());
inventoryOuterDetailService.deleteByOuterCode(outerCodeList); }
outerService.deleteInventoryOuterByIds(inventoryOuters.stream().map(item -> item.getId().toString()).collect(Collectors.joining(",")));
} }
Map<String, Long> outerSumMap = inventoryOuters.stream().collect(Collectors.toMap(InventoryOuter::getProductCode, InventoryOuter::getQuantity, Long::sum)); Map<String, Long> outerSumMap = inventoryOuters.stream().collect(Collectors.toMap(InventoryOuter::getProductCode, InventoryOuter::getQuantity, Long::sum));
@ -353,5 +391,182 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
if (CollUtil.isNotEmpty(updateMap.values())) { if (CollUtil.isNotEmpty(updateMap.values())) {
productInfoService.updateCount(new ArrayList<>(updateMap.values())); productInfoService.updateCount(new ArrayList<>(updateMap.values()));
} }
// 撤回时处理应收应付与发货撤回一致按发货记录逐个判断并处理金额是否变化为“是”则整单跳过制造商为P001的该发货记录跳过
boolean orderAmountChanged = isOrderRecallAmountChanged(projectOrderInfo.getOrderCode());
for (InventoryDelivery inventoryDelivery : inventoryDeliveryList) {
boolean skipReceivablePayable = isManufacturerP001(inventoryDelivery.getProductCode()) || orderAmountChanged;
inventoryDeliveryService.handleRecallReceivablePayable(
inventoryDelivery.getId(), inventoryDelivery.getOuterCode(), skipReceivablePayable);
}
}
/**
*
* / extendField3
*
* @param orderCode businessKey
* @return true
*/
private boolean isOrderRecallAmountChanged(String orderCode) {
Todo query = new Todo()
.setProcessKey(processConfig.getDefinition().getOrderReback())
.setBusinessKey(orderCode);
// 先查已办,再查待办
List<Todo> todos = todoMapper.selectTodoCompletedList(query);
if (CollUtil.isEmpty(todos)) {
Todo todo = todoMapper.selectTodo(query);
if (todo != null) {
todos = Collections.singletonList(todo);
}
}
return CollUtil.isNotEmpty(todos) && "是".equals(todos.get(0).getExtendField3());
}
/**
* P001
*
* @param productCode
* @return P001 true
*/
private boolean isManufacturerP001(String productCode) {
if (StringUtils.isEmpty(productCode)) {
return false;
}
List<ProductInfo> products = productInfoService.selectProductInfoByCodeList(Collections.singletonList(productCode));
if (CollUtil.isEmpty(products)) {
return false;
}
return "P001".equals(products.get(0).getVendorCode());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void applyRecall(Long id, String reason, String amountChanged) {
ProjectOrderInfo projectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoById(id);
if (projectOrderInfo == null) {
throw new ServiceException("订单不存在");
}
String businessKey = projectOrderInfo.getOrderCode();
// 已存在审批中的撤单流程时,不允许重复提交
ProcessInstance processInstance = todoService.getProcessInstance(businessKey);
if (processInstance != null) {
throw new ServiceException("该订单已提交撤单审批,请勿重复提交");
}
// 标记订单撤单审批状态为待审核
ProjectOrderInfo updateOrder = new ProjectOrderInfo();
updateOrder.setId(id);
updateOrder.setRebackApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode());
updateOrder.setUpdateTime(new Date());
updateOrder.setUpdateBy(ShiroUtils.getUserId().toString());
projectOrderInfoMapper.updateProjectOrderInfo(updateOrder);
// 启动撤单审批流程 order_rebackextendField1 存订单版本号extendField2 存撤单原因extendField3 存金额是否变化)
todoService.startProcessDeleteBefore(businessKey, businessKey,
new HashMap<String, Object>() {{
put("applyUserName", ShiroUtils.getSysUser().getUserName());
put("applyUser", ShiroUtils.getUserId());
put("reason", reason);
put("extendField1", projectOrderInfo.getVersionCode());
put("extendField2", reason);
put("extendField3", amountChanged);
put("orderId", id);
}}, processConfig.getDefinition().getOrderReback());
}
// ======================= 撤单审批order_reback回调 =======================
@Override
public Object todoDetail(String businessKey, String processKey, String todoId) {
return buildRecallApproveDetail(businessKey, todoId);
}
@Override
public Object completedTodoDetail(String businessKey, String processKey, String todoId) {
return buildRecallApproveDetail(businessKey, todoId);
}
@Override
public void fillBusinessInfo(List<Todo> todoCompletedList) {
// 待办/已办列表业务信息填充,暂不需要
}
@Override
public boolean todoApproveCallback(Todo todo) {
// 驳回时,将订单撤单审批状态标记为已驳回
Integer approveBtn = todo.getVariables() == null ? null : (Integer) todo.getVariables().get("approveBtn");
if (approveBtn != null && approveBtn == 0) {
String businessKey = todo.getBusinessKey();
if (StringUtils.isNotBlank(businessKey)) {
ProjectOrderInfo projectOrderInfo = projectOrderInfoService.selectProjectOrderInfoByOrderCode(businessKey);
if (projectOrderInfo != null) {
ProjectOrderInfo updateOrder = new ProjectOrderInfo();
updateOrder.setId(projectOrderInfo.getId());
updateOrder.setRebackApproveStatus(ApproveStatusEnum.APPROVE_REJECT.getCode());
updateOrder.setUpdateTime(new Date());
updateOrder.setUpdateBy(ShiroUtils.getUserId().toString());
projectOrderInfoMapper.updateProjectOrderInfo(updateOrder);
}
}
}
return TodoCommonTemplate.super.todoApproveCallback(todo);
}
@Override
public boolean multiInstanceApproveCallback(String activityName, ProcessInstance processInstance) {
if (processConfig.getDefinition().getOrderReback().equals(processInstance.getProcessDefinitionKey())
&& "领导".equals(activityName)) {
// 统计该节点全部已办记录:所有审批人均完成且全部批准后,才执行实际撤单业务
List<Todo> approveRecords = todoMapper.selectTodoCompletedList(new Todo()
.setProcessInstanceId(processInstance.getId())
.setTaskName("领导"));
boolean allApproved = CollUtil.isNotEmpty(approveRecords)
&& approveRecords.stream().allMatch(t -> Integer.valueOf(3).equals(t.getApproveStatus()));
if (allApproved) {
Map<String, Object> processVariables = processInstance.getProcessVariables();
Object orderIdObj = processVariables.get("orderId");
if (orderIdObj == null) {
throw new ServiceException("无法获取订单信息,撤单审批异常");
}
// 取该流程实例已办记录中 id 正序第一条的 approve_user作为撤单操作的更新人
Todo firstCompleted = todoMapper.selectFirstCompletedByProcessInstanceId(processInstance.getId());
String updateBy = firstCompleted != null && StringUtils.isNotBlank(firstCompleted.getApproveUser())
? firstCompleted.getApproveUser() : ShiroUtils.getUserId().toString();
Long orderId = Long.valueOf(orderIdObj.toString());
// 标记订单撤单审批状态为审批完成
ProjectOrderInfo updateOrder = new ProjectOrderInfo();
updateOrder.setId(orderId);
updateOrder.setRebackApproveStatus(ApproveStatusEnum.APPROVE_COMPLETE.getCode());
updateOrder.setUpdateTime(new Date());
updateOrder.setUpdateBy(updateBy);
projectOrderInfoMapper.updateProjectOrderInfo(updateOrder);
// 撤单审批通过不重置订单审批状态orderStatus保持原状态
recall(orderId, updateBy, false);
}
}
return TodoCommonTemplate.super.multiInstanceApproveCallback(activityName, processInstance);
}
/**
*
*
* @param orderCode
* @param todoId /id
* @return
*/
private Map<String, Object> buildRecallApproveDetail(String orderCode, String todoId) {
// 撤单原因存储于待办/已办记录的扩展字段 extendField2版本号存储于 extendField1
Todo todo = todoService.selectTodo(new Todo().setTodoId(todoId));
if (todo == null) {
todo = todoService.selectTodoCompleted(new Todo().setTodoId(todoId));
}
ProjectOrderInfo projectOrderInfo = StringUtils.isNotBlank(orderCode)
? projectOrderInfoService.selectProjectOrderInfoByOrderCode(orderCode)
: null;
if (projectOrderInfo == null) {
throw new ServiceException("订单不存在或已撤回");
}
Map<String, Object> result = new HashMap<>();
result.put("reason", todo != null ? todo.getExtendField2() : null);
result.put("projectOrderInfo", projectOrderInfo);
return result;
} }
} }

View File

@ -7,13 +7,19 @@ import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.config.flow.ProcessConfig;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.enums.ApproveStatusEnum;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils; import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.sip.domain.*; import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.dto.ApiDataQueryDto; import com.ruoyi.sip.dto.ApiDataQueryDto;
import com.ruoyi.sip.dto.inventory.InventoryDeliveryDetailExcelDto; import com.ruoyi.sip.dto.inventory.InventoryDeliveryDetailExcelDto;
import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.flowable.mapper.TodoMapper;
import com.ruoyi.sip.flowable.service.TodoCommonTemplate;
import com.ruoyi.sip.flowable.service.TodoService;
import com.ruoyi.sip.mapper.InventoryInfoMapper; import com.ruoyi.sip.mapper.InventoryInfoMapper;
import com.ruoyi.sip.mapper.InventoryOuterDetailMapper; import com.ruoyi.sip.mapper.InventoryOuterDetailMapper;
import com.ruoyi.sip.mapper.InventoryOuterMapper; import com.ruoyi.sip.mapper.InventoryOuterMapper;
@ -23,6 +29,8 @@ import com.ruoyi.sip.vo.DeliveryApproveVo;
import com.ruoyi.sip.vo.DeliveryInfoVo; import com.ruoyi.sip.vo.DeliveryInfoVo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
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.context.annotation.Lazy;
@ -43,7 +51,7 @@ import javax.annotation.Resource;
@Slf4j @Slf4j
@Service @Service
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService { public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService, TodoCommonTemplate {
@Autowired @Autowired
private InventoryDeliveryMapper inventoryDeliveryMapper; private InventoryDeliveryMapper inventoryDeliveryMapper;
@Autowired @Autowired
@ -77,6 +85,14 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
private OmsPurchaseOrderMapMapper omsPurchaseOrderMapMapper; private OmsPurchaseOrderMapMapper omsPurchaseOrderMapMapper;
@Resource @Resource
private InventoryInfoMapper inventoryInfoMapper; private InventoryInfoMapper inventoryInfoMapper;
@Autowired
private TodoService todoService;
@Autowired
private TodoMapper todoMapper;
@Autowired
private ProcessConfig processConfig;
@Autowired
private RuntimeService runtimeService;
@Value("${oms.inventory.innerTax:0.13}") @Value("${oms.inventory.innerTax:0.13}")
private String defaultTax; private String defaultTax;
@ -123,6 +139,8 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
if (orderInfo == null) { if (orderInfo == null) {
throw new ServiceException("订单信息不存在"); throw new ServiceException("订单信息不存在");
} }
//版本号取订单的version_code
inventoryDelivery.setVersionCode(orderInfo.getVersionCode());
if (StringUtils.isNotEmpty(inventoryDelivery.getPurchaseNo())) { if (StringUtils.isNotEmpty(inventoryDelivery.getPurchaseNo())) {
int newSnCount = CollUtil.isEmpty(productSnList) ? productSnDataList.size() : productSnList.size(); int newSnCount = CollUtil.isEmpty(productSnList) ? productSnDataList.size() : productSnList.size();
@ -344,34 +362,32 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
VendorInfo vendorInfo = vendorInfoService.selectVendorInfoByVendorCode(productInfo.getVendorCode()); VendorInfo vendorInfo = vendorInfoService.selectVendorInfoByVendorCode(productInfo.getVendorCode());
if (vendorInfo != null && VendorInfo.PayTypeEnum.OUTER_PAY.getCode().equals(vendorInfo.getPayType())) { if (vendorInfo != null && VendorInfo.PayTypeEnum.OUTER_PAY.getCode().equals(vendorInfo.getPayType())) {
List<InventoryInfo> inventoryInfos = inventoryInfoService.listByDeliveryId(inventoryDelivery.getId()); List<InventoryInfo> inventoryInfos = inventoryInfoService.listByDeliveryId(inventoryDelivery.getId());
//生成过应付单的不用再次生成 //生成过应付单的不用再次生成;已生成过(如撤回重发时残留的回写)则跳过应付单生成,不影响后续应收单
inventoryInfos = inventoryInfos.stream().filter(item -> StringUtils.isEmpty(item.getPayableBillCode())).collect(Collectors.toList()); inventoryInfos = inventoryInfos.stream().filter(item -> StringUtils.isEmpty(item.getPayableBillCode())).collect(Collectors.toList());
if (CollUtil.isEmpty(inventoryInfos)) { if (CollUtil.isNotEmpty(inventoryInfos)) {
return; OmsPayableBill payableBill = new OmsPayableBill();
payableBill.setProductCode(inventoryOuter.getProductCode());
payableBill.setProductType(productInfo.getType());
payableBill.setVendorCode(productInfo.getVendorCode());
payableBill.setInventoryCode(inventoryDelivery.getOuterCode());
BigDecimal allPrice = inventoryInfos.stream().map(InventoryInfo::getInnerPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
payableBill.setTotalPriceWithTax(allPrice);
BigDecimal defaultTaxRate = new BigDecimal(defaultTax);
BigDecimal allPriceWithOutTax = inventoryInfos.stream().map(item ->
{
BigDecimal taxRate = item.getTaxRate() == null ? defaultTaxRate : item.getTaxRate();
return item.getInnerPrice().divide(BigDecimal.ONE.add(taxRate), 2, RoundingMode.HALF_UP);
})
.reduce(BigDecimal.ZERO, BigDecimal::add);
payableBill.setTaxRate(inventoryInfos.get(0).getTaxRate() == null ? defaultTaxRate : inventoryInfos.get(0).getTaxRate());
payableBill.setTotalPriceWithoutTax(allPriceWithOutTax);
payableBill.setTaxAmount(allPrice.subtract(payableBill.getTotalPriceWithoutTax()));
payableBill.setProductCode(inventoryDelivery.getProductCode());
payableBill.setOrderCode(inventoryDelivery.getOrderCode());
payableBillService.insertOmsPayableBill(payableBill, vendorInfo.getPayConfigDay());
List<InventoryInfo> saveList = inventoryInfos.stream().peek(item -> item.setPayableBillCode(payableBill.getPayableBillCode())).collect(Collectors.toList());
inventoryInfoService.saveBatch(saveList);
} }
OmsPayableBill payableBill = new OmsPayableBill();
payableBill.setProductCode(inventoryOuter.getProductCode());
// payableBill.setEstimatedPaymentTime(DateUtils.addDays(DateUtils.getNowDate(), vendorInfo.getPayConfigDay()));
payableBill.setProductType(productInfo.getType());
payableBill.setVendorCode(productInfo.getVendorCode());
payableBill.setInventoryCode(inventoryDelivery.getOuterCode());
BigDecimal allPrice = inventoryInfos.stream().map(InventoryInfo::getInnerPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
payableBill.setTotalPriceWithTax(allPrice);
BigDecimal defaultTaxRate = new BigDecimal(defaultTax);
BigDecimal allPriceWithOutTax = inventoryInfos.stream().map(item ->
{
BigDecimal taxRate = item.getTaxRate() == null ? defaultTaxRate : item.getTaxRate();
return item.getInnerPrice().divide(BigDecimal.ONE.add(taxRate), 2, RoundingMode.HALF_UP);
})
.reduce(BigDecimal.ZERO, BigDecimal::add);
payableBill.setTaxRate(inventoryInfos.get(0).getTaxRate() == null ? defaultTaxRate : inventoryInfos.get(0).getTaxRate());
payableBill.setTotalPriceWithoutTax(allPriceWithOutTax);
payableBill.setTaxAmount(allPrice.subtract(payableBill.getTotalPriceWithoutTax()));
payableBill.setProductCode(inventoryDelivery.getProductCode());
payableBill.setOrderCode(inventoryDelivery.getOrderCode());
payableBillService.insertOmsPayableBill(payableBill, vendorInfo.getPayConfigDay());
List<InventoryInfo> saveList = inventoryInfos.stream().peek(item -> item.setPayableBillCode(payableBill.getPayableBillCode())).collect(Collectors.toList());
inventoryInfoService.saveBatch(saveList);
} }
//生成应收单 //生成应收单
OmsReceivableBill receivableBill = new OmsReceivableBill(); OmsReceivableBill receivableBill = new OmsReceivableBill();
@ -388,15 +404,24 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
BigDecimal price = projectProductInfo.getPrice(); BigDecimal price = projectProductInfo.getPrice();
InventoryDelivery inventoryDelivery1 = selectInventoryDeliveryById(inventoryDelivery.getId()); InventoryDelivery inventoryDelivery1 = selectInventoryDeliveryById(inventoryDelivery.getId());
BigDecimal allPrice = price.multiply(new BigDecimal(inventoryDelivery1.getQuantity().toString())); BigDecimal allPrice = price.multiply(new BigDecimal(inventoryDelivery1.getQuantity().toString()));
receivableBill.setTotalPriceWithTax(allPrice); //防重:同一出库单+产品且金额一致的应收单已生成过则不重复生成(避免重复确认/并发导致重复)
BigDecimal defaultTaxRate = projectProductInfo.getTaxRate() == null ? new BigDecimal(defaultTax) : projectProductInfo.getTaxRate().divide(new BigDecimal("100")); OmsReceivableBill receivableQuery = new OmsReceivableBill();
BigDecimal allPriceWithOutTax = allPrice.divide(BigDecimal.ONE.add(defaultTaxRate), 2, RoundingMode.HALF_UP); receivableQuery.setInventoryCode(inventoryDelivery.getOuterCode());
receivableBill.setTaxRate(defaultTaxRate); receivableQuery.setProductCode(inventoryOuter.getProductCode());
receivableBill.setTotalPriceWithoutTax(allPriceWithOutTax); List<OmsReceivableBill> existReceivableBills = billService.selectOmsReceivableBillList(receivableQuery);
receivableBill.setTaxAmount(allPrice.subtract(receivableBill.getTotalPriceWithoutTax())); boolean receivableDuplicated = existReceivableBills.stream()
receivableBill.setUninvoicedAmount(allPrice); .anyMatch(item -> item.getTotalPriceWithTax() != null && item.getTotalPriceWithTax().compareTo(allPrice) == 0);
receivableBill.setUnreceivedAmount(allPrice); if (!receivableDuplicated) {
billService.insertOmsReceivableBill(receivableBill); receivableBill.setTotalPriceWithTax(allPrice);
BigDecimal defaultTaxRate = projectProductInfo.getTaxRate() == null ? new BigDecimal(defaultTax) : projectProductInfo.getTaxRate().divide(new BigDecimal("100"));
BigDecimal allPriceWithOutTax = allPrice.divide(BigDecimal.ONE.add(defaultTaxRate), 2, RoundingMode.HALF_UP);
receivableBill.setTaxRate(defaultTaxRate);
receivableBill.setTotalPriceWithoutTax(allPriceWithOutTax);
receivableBill.setTaxAmount(allPrice.subtract(receivableBill.getTotalPriceWithoutTax()));
receivableBill.setUninvoicedAmount(allPrice);
receivableBill.setUnreceivedAmount(allPrice);
billService.insertOmsReceivableBill(receivableBill);
}
} }
//生成服务应收单、应付单 //生成服务应收单、应付单
@ -544,15 +569,207 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
return resultList; return resultList;
} }
/**
*
* todoApproveCallback
*
* @param id
* @param reason
* @param amountChanged
*/
@Override
public void applyRecall(Long id, String reason, String amountChanged) {
InventoryDelivery inventoryDelivery = inventoryDeliveryMapper.selectInventoryDeliveryById(id);
if (inventoryDelivery == null) {
throw new ServiceException("发货记录不存在");
}
// 当日创建的发货记录直接执行撤回,无需提交审批
if (isSameDay(inventoryDelivery.getCreateTime(), new Date())) {
throw new ServiceException("当日发货的记录请直接执行撤回操作");
}
String businessKey = inventoryDelivery.getOuterCode();
// 已存在审批中的撤回流程时,不允许重复提交
ProcessInstance processInstance = todoService.getProcessInstance(businessKey);
if (processInstance != null) {
throw new ServiceException("该发货记录已提交撤回审批,请勿重复提交");
}
// 标记撤回审批中
inventoryDelivery.setApproveStatus(ApproveStatusEnum.WAIT_APPROVE.getCode());
inventoryDeliveryMapper.updateInventoryDelivery(inventoryDelivery);
// 启动出库撤回审批流程 outer_rebackdeliveryId 关联具体发货记录extendField2 持久化到待办/已办)
todoService.startProcessDeleteBefore(businessKey, businessKey,
new HashMap<String, Object>() {{
put("applyUserName", ShiroUtils.getSysUser().getUserName());
put("applyUser", ShiroUtils.getUserId());
put("reason", reason);
put("extendField1", reason);
put("extendField2", String.valueOf(id));
put("extendField3", amountChanged);
put("deliveryId", id);
}}, processConfig.getDefinition().getOuterReback());
}
/**
*
*/
private boolean isSameDay(Date date1, Date date2) {
if (date1 == null || date2 == null) {
return false;
}
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date1);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
&& cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH)
&& cal1.get(Calendar.DAY_OF_MONTH) == cal2.get(Calendar.DAY_OF_MONTH);
}
// ======================= 出库撤回审批outer_reback回调 =======================
@Override
public Object todoDetail(String businessKey, String processKey, String todoId) {
return buildRecallApproveDetail(businessKey, todoId);
}
@Override
public Object completedTodoDetail(String businessKey, String processKey, String todoId) {
return buildRecallApproveDetail(businessKey, todoId);
}
@Override
public void fillBusinessInfo(List<Todo> todoCompletedList) {
// 待办/已办列表业务信息填充,暂不需要
}
@Override
public boolean todoApproveCallback(Todo todo) {
if (CollUtil.isEmpty(todo.getVariables())) {
return TodoCommonTemplate.super.todoApproveCallback(todo);
}
Integer approveBtn = (Integer) todo.getVariables().get("approveBtn");
if (approveBtn != null && approveBtn == 0) {
// 审批驳回:标记撤回已驳回,发货记录状态不变
String businessKey = todo.getBusinessKey();
String[] split = businessKey.split("#");
String outerCode = split.length > 1 ? split[1] : split[0];
log.info("出库撤回审批驳回,出库单号: {}", outerCode);
InventoryDelivery delivery = null;
if (todo.getExtendField2() != null && !todo.getExtendField2().isEmpty()) {
delivery = inventoryDeliveryMapper.selectInventoryDeliveryById(Long.valueOf(todo.getExtendField2()));
}
if (delivery != null) {
InventoryDelivery update = new InventoryDelivery();
update.setId(delivery.getId());
update.setApproveStatus(ApproveStatusEnum.APPROVE_REJECT.getCode());
inventoryDeliveryMapper.updateInventoryDelivery(update);
}
}
return TodoCommonTemplate.super.todoApproveCallback(todo);
}
@Override
public boolean multiInstanceApproveCallback(String activityName, ProcessInstance processInstance) {
if (processConfig.getDefinition().getOuterReback().equals(processInstance.getProcessDefinitionKey())
&& "领导".equals(activityName)) {
// 统计该节点全部已办记录:所有审批人均完成且全部批准后,才执行实际撤回业务
List<Todo> approveRecords = todoMapper.selectTodoCompletedList(new Todo()
.setProcessInstanceId(processInstance.getId())
.setTaskName("领导"));
boolean allApproved = CollUtil.isNotEmpty(approveRecords)
&& approveRecords.stream().allMatch(t -> Integer.valueOf(3).equals(t.getApproveStatus()));
if (allApproved) {
Map<String, Object> processVariables = processInstance.getProcessVariables();
Object deliveryIdObj = processVariables.get("deliveryId");
if (deliveryIdObj == null) {
throw new ServiceException("无法获取发货记录信息,撤回审批异常");
}
InventoryDelivery delivery = inventoryDeliveryMapper.selectInventoryDeliveryById(Long.valueOf(deliveryIdObj.toString()));
if (delivery == null) {
throw new ServiceException("发货记录不存在或已撤回,无法执行撤回");
}
// 取该流程实例已办记录中 id 正序第一条的 approve_user作为撤回操作的更新人
Todo firstCompleted = todoMapper.selectFirstCompletedByProcessInstanceId(processInstance.getId());
String updateBy = firstCompleted != null && StringUtils.isNotBlank(firstCompleted.getApproveUser())
? firstCompleted.getApproveUser() : ShiroUtils.getUserId().toString();
recall(delivery.getId(), updateBy);
// 审批通过:出库单标记为已撤回(按 outerCode 匹配)
if (StringUtils.isNotBlank(delivery.getOuterCode())) {
inventoryOuterMapper.updateDeliveryStatusByOuterCode(delivery.getOuterCode(),
InventoryOuter.DeliveryStatusEnum.REBACK.getCode());
// 参照撤销出库单业务(不物理删除出库单及其明细):
// 1. 回补实时库存
InventoryOuter outer = inventoryOuterMapper.selectInventoryOuterByCode(delivery.getOuterCode());
if (outer != null) {
productInfoService.updateAvailableCount(outer.getQuantity(), outer.getProductCode());
ProjectOrderInfo projectOrderInfo = new ProjectOrderInfo();
projectOrderInfo.setOrderCode(outer.getOrderCode());
projectOrderInfo.setOuterStatus(ProjectOrderInfo.OuterStatusEnum.PART_OUTER.getCode());
// 2. 该订单已无其他有效出库单countByOrderCode 已过滤已撤回的 delivery_status=3将项目订单出库状态置为未出库
if (inventoryOuterMapper.countByOrderCode(outer.getOrderCode()) <= 0) {
projectOrderInfo.setOuterStatus(ProjectOrderInfo.OuterStatusEnum.NOT_OUTER.getCode());
}
projectOrderInfoService.updateProjectOrderInfoByCode(projectOrderInfo);
}
}
// 审批通过:标记撤回审批完成
InventoryDelivery update = new InventoryDelivery();
update.setId(delivery.getId());
update.setApproveStatus(ApproveStatusEnum.APPROVE_COMPLETE.getCode());
inventoryDeliveryMapper.updateInventoryDelivery(update);
}
}
return TodoCommonTemplate.super.multiInstanceApproveCallback(activityName, processInstance);
}
/**
*
*
* @param outerCode
* @param todoId /id
* @return
*/
private Map<String, Object> buildRecallApproveDetail(String outerCode, String todoId) {
// 申请说明存储于待办/已办记录的扩展字段 extendField1发货记录id 存储于 extendField2
Todo todo = todoService.selectTodo(new Todo().setTodoId(todoId));
if (todo == null) {
todo = todoService.selectTodoCompleted(new Todo().setTodoId(todoId));
}
InventoryDelivery delivery = null;
if (todo != null && todo.getExtendField2() != null && !todo.getExtendField2().isEmpty()) {
delivery = inventoryDeliveryMapper.selectInventoryDeliveryById(Long.valueOf(todo.getExtendField2()));
}
if (delivery == null) {
throw new ServiceException("发货记录不存在或已撤回");
}
List<String> productSnList = deliveryDetailService.selectOmsInventoryDeliveryDetailByDeliveryId(delivery.getId())
.stream()
.map(OmsInventoryDeliveryDetail::getProductSn)
.collect(Collectors.toList());
Map<String, Object> result = new HashMap<>();
result.put("reason", todo != null ? todo.getExtendField1() : null);
result.put("amountChanged", todo != null ? todo.getExtendField3() : null);
result.put("delivery", delivery);
result.put("productSnList", productSnList);
return result;
}
@Override @Override
public void recall(Long id) { public void recall(Long id) {
//todo 判断应付或应收状态 不允许退 recall(id, ShiroUtils.getUserId().toString());
List<DeliveryApproveVo> deliveryApproveVoList = inventoryDeliveryMapper.selectDeliveryApproveList(id); }
if (CollectionUtils.isNotEmpty(deliveryApproveVoList)) {
throw new ServiceException("存在已完成或审批中的应收、应付信息,无法执行撤回操作");
}
/**
*
*
* @param id
* @param updateBy id
*/
public void recall(Long id, String updateBy) {
InventoryDelivery inventoryDelivery = inventoryDeliveryMapper.selectInventoryDeliveryById(id); InventoryDelivery inventoryDelivery = inventoryDeliveryMapper.selectInventoryDeliveryById(id);
// 制造商编码为 P001 的产品,或 撤回审批中“金额是否变化”为“是”时,跳过应收/应付相关的判断与处理
boolean skipReceivablePayable = isManufacturerP001(inventoryDelivery.getProductCode())
|| isRecallAmountChanged(id);
ProjectOrderInfo projectOrderInfo = projectOrderInfoService.selectProjectOrderInfoByOrderCode(inventoryDelivery.getOrderCode()); ProjectOrderInfo projectOrderInfo = projectOrderInfoService.selectProjectOrderInfoByOrderCode(inventoryDelivery.getOrderCode());
deleteInventoryOuterById(id, false, projectOrderInfo.getOrderCode()); deleteInventoryOuterById(id, false, projectOrderInfo.getOrderCode());
List<ProjectProductInfo> projectProductInfos = projectProductInfoService.listDeliveryProductByOrderCode(Collections.singletonList(inventoryDelivery.getOrderCode())); List<ProjectProductInfo> projectProductInfos = projectProductInfoService.listDeliveryProductByOrderCode(Collections.singletonList(inventoryDelivery.getOrderCode()));
@ -580,36 +797,149 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
ProjectOrderInfo updateOrder = new ProjectOrderInfo(); ProjectOrderInfo updateOrder = new ProjectOrderInfo();
updateOrder.setOrderCode(inventoryDelivery.getOrderCode()); updateOrder.setOrderCode(inventoryDelivery.getOrderCode());
updateOrder.setUpdateTime(new Date()); updateOrder.setUpdateTime(new Date());
updateOrder.setUpdateBy(ShiroUtils.getUserId().toString()); updateOrder.setUpdateBy(updateBy);
updateOrder.setDeliveryStatus(sum == allSum ? ProjectOrderInfo.DeliveryStatusEnum.ALL_DELIVERY.getCode() : ProjectOrderInfo.DeliveryStatusEnum.PART_DELIVERY.getCode()); updateOrder.setDeliveryStatus(sum == allSum ? ProjectOrderInfo.DeliveryStatusEnum.ALL_DELIVERY.getCode() : ProjectOrderInfo.DeliveryStatusEnum.PART_DELIVERY.getCode());
updateOrder.setOperationVersion(projectOrderInfo.getOperationVersion() + 1); updateOrder.setOperationVersion(projectOrderInfo.getOperationVersion() + 1);
projectOrderInfoService.updateProjectOrderInfoByCode(updateOrder); projectOrderInfoService.updateProjectOrderInfoByCode(updateOrder);
//修改累计发货数量 //修改累计发货数量
productInfoService.updateCumulativeCount(-inventoryDelivery.getQuantity(), inventoryDelivery.getProductCode()); productInfoService.updateCumulativeCount(-inventoryDelivery.getQuantity(), inventoryDelivery.getProductCode());
//撤回时删除当前出库单对应的应付、应收数据仅删除软件和硬件类型1、2 //撤回时处理当前出库单对应的应付、应收数据仅处理软件和硬件类型1、2
handleRecallReceivablePayable(id, inventoryDelivery.getOuterCode(), skipReceivablePayable);
}
/**
*
* ////
*
* @param deliveryId
* @param outerCode /
* @param skipReceivablePayable
*/
@Override
public void handleRecallReceivablePayable(Long deliveryId, String outerCode, boolean skipReceivablePayable) {
if (skipReceivablePayable) {
return;
}
// 是否存在应收/应付财务单据(付款/收票/收款/开票单):无则删除原应收应付,有则改为生成红冲负金额单
List<DeliveryApproveVo> deliveryApproveVoList = inventoryDeliveryMapper.selectDeliveryApproveList(deliveryId);
boolean hasFinanceBill = CollUtil.isNotEmpty(deliveryApproveVoList);
// 仅处理软件和硬件类型1、2
Set<String> deleteProductTypeSet = new HashSet<>(Arrays.asList( Set<String> deleteProductTypeSet = new HashSet<>(Arrays.asList(
ProductInfo.ProductTypeEnum.SOFTWARE.getType(), ProductInfo.ProductTypeEnum.SOFTWARE.getType(),
ProductInfo.ProductTypeEnum.HARDWARE.getType() ProductInfo.ProductTypeEnum.HARDWARE.getType()
)); ));
OmsPayableBill queryPayable = new OmsPayableBill(); OmsPayableBill queryPayable = new OmsPayableBill();
queryPayable.setInventoryCode(inventoryDelivery.getOuterCode()); queryPayable.setInventoryCode(outerCode);
List<OmsPayableBill> payableBills = payableBillService.selectOmsPayableBillList(queryPayable).stream() List<OmsPayableBill> payableBills = payableBillService.selectOmsPayableBillList(queryPayable).stream()
.filter(item -> deleteProductTypeSet.contains(item.getProductType())) .filter(item -> deleteProductTypeSet.contains(item.getProductType()))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (CollUtil.isNotEmpty(payableBills)) {
String ids = payableBills.stream().map(item -> String.valueOf(item.getId())).collect(Collectors.joining(","));
payableBillService.deleteOmsPayableBillByIds(ids);
}
OmsReceivableBill queryReceivable = new OmsReceivableBill(); OmsReceivableBill queryReceivable = new OmsReceivableBill();
queryReceivable.setInventoryCode(inventoryDelivery.getOuterCode()); queryReceivable.setInventoryCode(outerCode);
List<OmsReceivableBill> receivableBills = billService.selectOmsReceivableBillList(queryReceivable).stream() List<OmsReceivableBill> receivableBills = billService.selectOmsReceivableBillList(queryReceivable).stream()
.filter(item -> deleteProductTypeSet.contains(item.getProductType())) .filter(item -> deleteProductTypeSet.contains(item.getProductType()))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (CollUtil.isNotEmpty(receivableBills)) { if (hasFinanceBill) {
String ids = receivableBills.stream().map(item -> String.valueOf(item.getId())).collect(Collectors.joining(",")); // 存在应收/应付财务单据(未完成或已完成):不删除原单,改为生成红冲负金额应收、应付单
billService.deleteOmsReceivableBillByIds(ids); generateRecallRedRushBill(payableBills, receivableBills);
} else {
// 无应收/应付财务单据:直接删除对应的应付、应收信息
if (CollUtil.isNotEmpty(payableBills)) {
String ids = payableBills.stream().map(item -> String.valueOf(item.getId())).collect(Collectors.joining(","));
payableBillService.deleteOmsPayableBillByIds(ids);
}
if (CollUtil.isNotEmpty(receivableBills)) {
String ids = receivableBills.stream().map(item -> String.valueOf(item.getId())).collect(Collectors.joining(","));
billService.deleteOmsReceivableBillByIds(ids);
}
} }
//清空本发货单库存明细上的应付单号,保证撤回后重新确认发货可再次生成应付单
List<InventoryInfo> recallInventoryInfos = inventoryInfoService.listByDeliveryId(deliveryId);
if (CollUtil.isNotEmpty(recallInventoryInfos)) {
inventoryInfoService.clearPayableBillCodeByIds(recallInventoryInfos.stream().map(InventoryInfo::getId).collect(Collectors.toList()));
}
}
/**
*
* / extendField3id extendField2
*
* @param deliveryId
* @return true
*/
private boolean isRecallAmountChanged(Long deliveryId) {
Todo query = new Todo()
.setProcessKey(processConfig.getDefinition().getOuterReback())
.setExtendField2(String.valueOf(deliveryId));
// 先查待办,再查已办(审批通过后已办记录仍在)
List<Todo> todos = todoMapper.selectTodoCompletedList(query);
if (CollUtil.isEmpty(todos)) {
Todo todo = todoMapper.selectTodo(query);
if (todo != null) {
todos = Collections.singletonList(todo);
}
}
return CollUtil.isNotEmpty(todos) && "是".equals(todos.get(0).getExtendField3());
}
/**
* P001
*
* @param productCode
* @return P001 true
*/
private boolean isManufacturerP001(String productCode) {
if (StringUtils.isEmpty(productCode)) {
return false;
}
List<ProductInfo> products = productInfoService.selectProductInfoByCodeList(Collections.singletonList(productCode));
if (CollUtil.isEmpty(products)) {
return false;
}
return "P001".equals(products.get(0).getVendorCode());
}
/**
* /
*
* @param payableBills /
* @param receivableBills /
*/
private void generateRecallRedRushBill(List<OmsPayableBill> payableBills, List<OmsReceivableBill> receivableBills) {
if (CollUtil.isNotEmpty(payableBills)) {
for (OmsPayableBill src : payableBills) {
OmsPayableBill redRush = new OmsPayableBill();
redRush.setVendorCode(src.getVendorCode());
redRush.setOrderCode(src.getOrderCode());
redRush.setInventoryCode(src.getInventoryCode());
redRush.setProductCode(src.getProductCode());
redRush.setProductType(src.getProductType());
redRush.setProductLevel2Type(src.getProductLevel2Type());
redRush.setTaxRate(src.getTaxRate());
// 负金额红冲
redRush.setTotalPriceWithTax(src.getTotalPriceWithTax() == null ? null : src.getTotalPriceWithTax().negate());
redRush.setTotalPriceWithoutTax(src.getTotalPriceWithoutTax() == null ? null : src.getTotalPriceWithoutTax().negate());
redRush.setTaxAmount(src.getTaxAmount() == null ? null : src.getTaxAmount().negate());
payableBillService.insertOmsPayableBill(redRush, 0);
}
}
if (CollUtil.isNotEmpty(receivableBills)) {
for (OmsReceivableBill src : receivableBills) {
OmsReceivableBill redRush = new OmsReceivableBill();
redRush.setPartnerCode(src.getPartnerCode());
redRush.setPartnerName(src.getPartnerName());
redRush.setOrderCode(src.getOrderCode());
redRush.setInventoryCode(src.getInventoryCode());
redRush.setProductCode(src.getProductCode());
redRush.setProductType(src.getProductType());
redRush.setTaxRate(src.getTaxRate());
// 负金额红冲
redRush.setTotalPriceWithTax(src.getTotalPriceWithTax() == null ? null : src.getTotalPriceWithTax().negate());
redRush.setTotalPriceWithoutTax(src.getTotalPriceWithoutTax() == null ? null : src.getTotalPriceWithoutTax().negate());
redRush.setTaxAmount(src.getTaxAmount() == null ? null : src.getTaxAmount().negate());
billService.insertOmsReceivableBill(redRush);
}
}
} }
@Override @Override

View File

@ -183,6 +183,11 @@ public class InventoryInfoServiceImpl implements IInventoryInfoService {
inventoryInfoMapper.clearOutInfo(idList); inventoryInfoMapper.clearOutInfo(idList);
} }
@Override
public void clearPayableBillCodeByIds(List<Long> idList) {
inventoryInfoMapper.clearPayableBillCodeByIds(idList);
}
@Override @Override
public List<String> checkUnq(List<String> productSnList) { public List<String> checkUnq(List<String> productSnList) {
List<InventoryInfo> inventoryInfos = inventoryInfoMapper.countBySn(productSnList); List<InventoryInfo> inventoryInfos = inventoryInfoMapper.countBySn(productSnList);

View File

@ -187,7 +187,6 @@ public class InventoryOuterServiceImpl implements IInventoryOuterService
orderInfoService.updateProjectOrderInfoByCode(projectOrderInfo); orderInfoService.updateProjectOrderInfoByCode(projectOrderInfo);
} }
return inventoryOuterMapper.deleteInventoryOuterById(id); return inventoryOuterMapper.deleteInventoryOuterById(id);
} }
@ -207,9 +206,10 @@ public class InventoryOuterServiceImpl implements IInventoryOuterService
//软硬件之和 //软硬件之和
long sum = projectProductInfos.stream().mapToLong(ProjectProductInfo::getQuantity).sum(); long sum = projectProductInfos.stream().mapToLong(ProjectProductInfo::getQuantity).sum();
List<InventoryOuter> list = inventoryOuterMapper.selectInventoryOuterList(queryDto); List<InventoryOuter> list = inventoryOuterMapper.selectInventoryOuterList(queryDto);
long count = list.stream().filter(item ->(item.getId().equals(inventoryOuter.getId()))|| long count = list.stream().filter(item -> !InventoryOuter.DeliveryStatusEnum.REBACK.getCode().equals(item.getDeliveryStatus())
&& (item.getId().equals(inventoryOuter.getId()) ||
//已确认和已接收数量 //已确认和已接收数量
InventoryOuter.OuterStatusEnum.WAIT_RECEIVE.getCode().equals(item.getOuterStatus()) || InventoryOuter.OuterStatusEnum.RECEIVED.getCode().equals(item.getOuterStatus())) InventoryOuter.OuterStatusEnum.WAIT_RECEIVE.getCode().equals(item.getOuterStatus()) || InventoryOuter.OuterStatusEnum.RECEIVED.getCode().equals(item.getOuterStatus())))
.mapToLong(InventoryOuter::getQuantity).sum(); .mapToLong(InventoryOuter::getQuantity).sum();
//部分接收 //部分接收
if (count == 0L) { if (count == 0L) {
@ -316,7 +316,6 @@ public class InventoryOuterServiceImpl implements IInventoryOuterService
.mapToLong(InventoryOuter::getQuantity).sum(); .mapToLong(InventoryOuter::getQuantity).sum();
outerViewVo.setCommitQuantity(sum2); outerViewVo.setCommitQuantity(sum2);
return outerViewVo; return outerViewVo;
} }
@Override @Override

View File

@ -68,6 +68,11 @@ public class OmsFinanceOperateReportServiceImpl implements IOmsFinanceOperateRep
return omsFinanceOperateReportMapper.selectOmsFinanceOperateReportList(omsFinanceOperateReport); return omsFinanceOperateReportMapper.selectOmsFinanceOperateReportList(omsFinanceOperateReport);
} }
@Override
public List<OmsFinanceOperateReport> selectOmsFinanceOperateReportSupplierList(OmsFinanceOperateReport omsFinanceOperateReport) {
return omsFinanceOperateReportMapper.selectOmsFinanceOperateReportSupplierList(omsFinanceOperateReport);
}
/** /**
* *
* *

View File

@ -95,6 +95,14 @@ public class OmsInventoryDeliveryDetailServiceImpl implements IOmsInventoryDeliv
@Override @Override
public void saveBatch(List<OmsInventoryDeliveryDetail> detailList) { public void saveBatch(List<OmsInventoryDeliveryDetail> detailList) {
if (detailList == null || detailList.isEmpty()) {
throw new IllegalArgumentException("参数列表不能为空");
}
for (OmsInventoryDeliveryDetail detail : detailList) {
if (detail.getProductSn() == null || detail.getProductSn().isEmpty()) {
throw new IllegalArgumentException("SN码不能为空");
}
}
omsInventoryDeliveryDetailMapper.saveBatch(detailList); omsInventoryDeliveryDetailMapper.saveBatch(detailList);
} }

View File

@ -46,6 +46,7 @@ import com.alibaba.fastjson.JSON;
import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.ApproveStatusEnum;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils; import com.ruoyi.common.utils.DictUtils;
@ -420,10 +421,19 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
@Override @Override
public int updateProjectOrderInfo(ProjectOrderInfo projectOrderInfo) { public int updateProjectOrderInfo(ProjectOrderInfo projectOrderInfo) {
ProjectOrderInfo existProjectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoById(projectOrderInfo.getId()); ProjectOrderInfo existProjectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoById(projectOrderInfo.getId());
// 撤单审批通过后允许重新编辑保存/提交审批
boolean rebackApproved = ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode().equals(existProjectOrderInfo.getOrderStatus())
&& "2".equals(existProjectOrderInfo.getRebackApproveStatus());
if (!(ProjectOrderInfo.OrderStatus.WAIT_COMMIT.getCode().equals(existProjectOrderInfo.getOrderStatus()) if (!(ProjectOrderInfo.OrderStatus.WAIT_COMMIT.getCode().equals(existProjectOrderInfo.getOrderStatus())
|| ProjectOrderInfo.OrderStatus.APPROVE_REJECT.getCode().equals(existProjectOrderInfo.getOrderStatus()))) { || ProjectOrderInfo.OrderStatus.APPROVE_REJECT.getCode().equals(existProjectOrderInfo.getOrderStatus())
|| rebackApproved)) {
throw new ServiceException("订单不处于待提交或已驳回状态,无法修改数据"); throw new ServiceException("订单不处于待提交或已驳回状态,无法修改数据");
} }
if (rebackApproved) {
// 订单重新保存/提交审批后,清除撤单审批状态
projectOrderInfo.setRebackApproveStatus(ApproveStatusEnum.WAIT_COMMIT.getCode());
projectOrderInfoMapper.clearRebackApproveStatus(projectOrderInfo.getId());
}
//更新BG属性 //更新BG属性
ProjectInfo projectInfo = new ProjectInfo(); ProjectInfo projectInfo = new ProjectInfo();
projectInfo.setId(projectOrderInfo.getProjectId()); projectInfo.setId(projectOrderInfo.getProjectId());

View File

@ -7,6 +7,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<resultMap type="OmsFinanceOperateReport" id="OmsFinanceOperateReportResult"> <resultMap type="OmsFinanceOperateReport" id="OmsFinanceOperateReportResult">
<result property="id" column="id" /> <result property="id" column="id" />
<result property="orderCode" column="order_code" /> <result property="orderCode" column="order_code" />
<result property="supplier" column="supplier" />
<result property="receivableWithTax" column="receivable_with_tax" /> <result property="receivableWithTax" column="receivable_with_tax" />
<result property="receivableWithoutTax" column="receivable_without_tax" /> <result property="receivableWithoutTax" column="receivable_without_tax" />
<result property="receivableTax" column="receivable_tax" /> <result property="receivableTax" column="receivable_tax" />
@ -147,6 +148,120 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectOmsFinanceOperateReportVo"/> <include refid="selectOmsFinanceOperateReportVo"/>
where id = #{id} where id = #{id}
</select> </select>
<select id="selectOmsFinanceOperateReportSupplierList" parameterType="OmsFinanceOperateReport" resultMap="OmsFinanceOperateReportResult">
select
t.id, t.order_code, t.supplier, t.receivable_with_tax, t.receivable_without_tax, t.receivable_tax, t.charge_status, t.charged_without_tax, t.gross_profit,
t.gross_profit_rate, t.biz_charge_date, t.finance_charge_date, t.receipt_status, t.received_with_tax, t.received_without_tax, t.received_tax,
t.receiving_with_tax, t.receiving_without_tax, t.receiving_tax, t.unreceived_with_tax, t.unreceived_without_tax, t.unreceived_tax, t.invoice_status,
t.invoiced_with_tax, t.invoiced_without_tax, t.invoiced_tax, t.invoicing_with_tax, t.invoicing_without_tax, t.invoicing_tax, t.uninvoiced_with_tax,
t.uninvoiced_without_tax, t.uninvoiced_tax, t.payable_with_tax, t.payable_without_tax, t.payable_tax, t.payment_status, t.paid_with_tax, t.paid_without_tax,
t.paid_tax, t.paying_with_tax, t.paying_without_tax, t.paying_tax, t.unpaid_with_tax, t.unpaid_without_tax, t.unpaid_tax, t.ticket_status, t.ticketed_with_tax,
t.ticketed_without_tax, t.ticketed_tax, t.ticketing_with_tax, t.ticketing_without_tax, t.ticketing_tax, t.unticketed_with_tax, t.unticketed_without_tax,
t.unticketed_tax, t.create_time, t.update_time
from (
select
min(t1.id) as id,
null as order_code,
t2.supplier as supplier,
sum(ifnull(t1.receivable_with_tax, 0)) as receivable_with_tax,
sum(ifnull(t1.receivable_without_tax, 0)) as receivable_without_tax,
sum(ifnull(t1.receivable_tax, 0)) as receivable_tax,
case
when sum(ifnull(t1.receivable_without_tax, 0)) = 0 then null
when sum(ifnull(t1.receivable_without_tax, 0)) = sum(ifnull(t1.charged_without_tax, 0)) then 'all'
when sum(ifnull(t1.charged_without_tax, 0)) = 0 then 'wait'
else 'part'
end as charge_status,
sum(ifnull(t1.charged_without_tax, 0)) as charged_without_tax,
sum(ifnull(t1.gross_profit, 0)) as gross_profit,
case
when sum(ifnull(t1.charged_without_tax, 0)) = 0 then 0
else round(sum(ifnull(t1.gross_profit, 0)) / sum(ifnull(t1.charged_without_tax, 0)), 4)
end as gross_profit_rate,
max(t1.biz_charge_date) as biz_charge_date,
max(t1.finance_charge_date) as finance_charge_date,
case
when sum(ifnull(t1.receivable_with_tax, 0)) = 0 then null
when sum(ifnull(t1.receivable_with_tax, 0)) = sum(ifnull(t1.received_with_tax, 0)) then 'all'
when sum(ifnull(t1.receivable_with_tax, 0)) = sum(ifnull(t1.unreceived_with_tax, 0)) then 'wait'
else 'part'
end as receipt_status,
sum(ifnull(t1.received_with_tax, 0)) as received_with_tax,
sum(ifnull(t1.received_without_tax, 0)) as received_without_tax,
sum(ifnull(t1.received_tax, 0)) as received_tax,
sum(ifnull(t1.receiving_with_tax, 0)) as receiving_with_tax,
sum(ifnull(t1.receiving_without_tax, 0)) as receiving_without_tax,
sum(ifnull(t1.receiving_tax, 0)) as receiving_tax,
sum(ifnull(t1.unreceived_with_tax, 0)) as unreceived_with_tax,
sum(ifnull(t1.unreceived_without_tax, 0)) as unreceived_without_tax,
sum(ifnull(t1.unreceived_tax, 0)) as unreceived_tax,
case
when sum(ifnull(t1.receivable_with_tax, 0)) = 0 then null
when sum(ifnull(t1.receivable_with_tax, 0)) = sum(ifnull(t1.invoiced_with_tax, 0)) then 'all'
when sum(ifnull(t1.receivable_with_tax, 0)) = sum(ifnull(t1.uninvoiced_with_tax, 0)) then 'wait'
else 'part'
end as invoice_status,
sum(ifnull(t1.invoiced_with_tax, 0)) as invoiced_with_tax,
sum(ifnull(t1.invoiced_without_tax, 0)) as invoiced_without_tax,
sum(ifnull(t1.invoiced_tax, 0)) as invoiced_tax,
sum(ifnull(t1.invoicing_with_tax, 0)) as invoicing_with_tax,
sum(ifnull(t1.invoicing_without_tax, 0)) as invoicing_without_tax,
sum(ifnull(t1.invoicing_tax, 0)) as invoicing_tax,
sum(ifnull(t1.uninvoiced_with_tax, 0)) as uninvoiced_with_tax,
sum(ifnull(t1.uninvoiced_without_tax, 0)) as uninvoiced_without_tax,
sum(ifnull(t1.uninvoiced_tax, 0)) as uninvoiced_tax,
sum(ifnull(t1.payable_with_tax, 0)) as payable_with_tax,
sum(ifnull(t1.payable_without_tax, 0)) as payable_without_tax,
sum(ifnull(t1.payable_tax, 0)) as payable_tax,
case
when sum(ifnull(t1.payable_with_tax, 0)) = 0 then null
when sum(ifnull(t1.payable_with_tax, 0)) = sum(ifnull(t1.paid_with_tax, 0)) then 'all'
when sum(ifnull(t1.payable_with_tax, 0)) = sum(ifnull(t1.unpaid_with_tax, 0)) then 'wait'
else 'part'
end as payment_status,
sum(ifnull(t1.paid_with_tax, 0)) as paid_with_tax,
sum(ifnull(t1.paid_without_tax, 0)) as paid_without_tax,
sum(ifnull(t1.paid_tax, 0)) as paid_tax,
sum(ifnull(t1.paying_with_tax, 0)) as paying_with_tax,
sum(ifnull(t1.paying_without_tax, 0)) as paying_without_tax,
sum(ifnull(t1.paying_tax, 0)) as paying_tax,
sum(ifnull(t1.unpaid_with_tax, 0)) as unpaid_with_tax,
sum(ifnull(t1.unpaid_without_tax, 0)) as unpaid_without_tax,
sum(ifnull(t1.unpaid_tax, 0)) as unpaid_tax,
case
when sum(ifnull(t1.payable_with_tax, 0)) = 0 then null
when sum(ifnull(t1.payable_with_tax, 0)) = sum(ifnull(t1.ticketed_with_tax, 0)) then 'all'
when sum(ifnull(t1.payable_with_tax, 0)) = sum(ifnull(t1.unticketed_with_tax, 0)) then 'wait'
else 'part'
end as ticket_status,
sum(ifnull(t1.ticketed_with_tax, 0)) as ticketed_with_tax,
sum(ifnull(t1.ticketed_without_tax, 0)) as ticketed_without_tax,
sum(ifnull(t1.ticketed_tax, 0)) as ticketed_tax,
sum(ifnull(t1.ticketing_with_tax, 0)) as ticketing_with_tax,
sum(ifnull(t1.ticketing_without_tax, 0)) as ticketing_without_tax,
sum(ifnull(t1.ticketing_tax, 0)) as ticketing_tax,
sum(ifnull(t1.unticketed_with_tax, 0)) as unticketed_with_tax,
sum(ifnull(t1.unticketed_without_tax, 0)) as unticketed_without_tax,
sum(ifnull(t1.unticketed_tax, 0)) as unticketed_tax,
max(t1.create_time) as create_time,
max(t1.update_time) as update_time
from oms_finance_operate_report t1
left join project_order_info t2 on t1.order_code = t2.order_code
where t2.supplier is not null
and t2.supplier != ''
<if test="supplier != null and supplier != ''">
and t2.supplier like concat('%', #{supplier}, '%')
</if>
group by t2.supplier
) t
<where>
<if test="chargeStatus != null and chargeStatus != ''"> and t.charge_status = #{chargeStatus}</if>
<if test="receiptStatus != null and receiptStatus != ''"> and t.receipt_status = #{receiptStatus}</if>
<if test="invoiceStatus != null and invoiceStatus != ''"> and t.invoice_status = #{invoiceStatus}</if>
<if test="paymentStatus != null and paymentStatus != ''"> and t.payment_status = #{paymentStatus}</if>
<if test="ticketStatus != null and ticketStatus != ''"> and t.ticket_status = #{ticketStatus}</if>
</where>
</select>
<select id="maxDataDate" resultType="java.util.Date"> <select id="maxDataDate" resultType="java.util.Date">
select max(data_date) from oms_finance_operate_report_detail select max(data_date) from oms_finance_operate_report_detail
</select> </select>

View File

@ -16,16 +16,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="applyTime" column="apply_time" /> <result property="applyTime" column="apply_time" />
<result property="extendField1" column="extend_field1" /> <result property="extendField1" column="extend_field1" />
<result property="extendField2" column="extend_field2" /> <result property="extendField2" column="extend_field2" />
<result property="extendField3" column="extend_field3" />
</resultMap> </resultMap>
<sql id="selectTodoVo"> <sql id="selectTodoVo">
select todo_id, business_key, process_key, process_name, task_name, approve_user_name,form_key, select todo_id, business_key, process_key, process_name, task_name, approve_user_name,form_key,
apply_user_name, apply_time, extend_field1, extend_field2,task_id,process_instance_id,approve_user from bu_todo apply_user_name, apply_time, extend_field1, extend_field2,extend_field3,task_id,process_instance_id,approve_user from bu_todo
</sql> </sql>
<sql id="selectTodoCompletedVo"> <sql id="selectTodoCompletedVo">
select todo_id, business_key, process_key, process_name, task_name, approve_user_name,approve_time,approve_opinion, select todo_id, business_key, process_key, process_name, task_name, approve_user_name,approve_time,approve_opinion,
approve_status,apply_user_name, apply_time, extend_field1, extend_field2,task_id,process_instance_id,form_key,approve_user from bu_todo_completed approve_status,apply_user_name, apply_time, extend_field1, extend_field2,extend_field3,task_id,process_instance_id,form_key,approve_user from bu_todo_completed
</sql> </sql>
<select id="selectTodoList" parameterType="Todo" resultType="todo"> <select id="selectTodoList" parameterType="Todo" resultType="todo">
@ -57,6 +58,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="extendField2 != null and extendField2 != ''">and extend_field2 like <if test="extendField2 != null and extendField2 != ''">and extend_field2 like
concat('%',#{extendField2},'%') concat('%',#{extendField2},'%')
</if> </if>
<if test="extendField3 != null and extendField3 != ''">and extend_field3 like
concat('%',#{extendField3},'%')
</if>
<if test="processInstanceId != null and processInstanceId != ''">and process_instance_id = <if test="processInstanceId != null and processInstanceId != ''">and process_instance_id =
#{processInstanceId} #{processInstanceId}
</if> </if>
@ -76,7 +80,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select todo_id, business_key, process_key, process_name, task_name, select todo_id, business_key, process_key, process_name, task_name,
approve_user_name,approve_time,approve_opinion, approve_user_name,approve_time,approve_opinion,
approve_status,apply_user_name, apply_time, extend_field1, approve_status,apply_user_name, apply_time, extend_field1,
extend_field2,task_id,process_instance_id,form_key,all_approve_user_name,approve_user from bu_todo_completed extend_field2,extend_field3,task_id,process_instance_id,form_key,all_approve_user_name,approve_user from bu_todo_completed
<where> <where>
<if test="todoId != null and todoId != ''">and todo_id = #{todoId}</if> <if test="todoId != null and todoId != ''">and todo_id = #{todoId}</if>
<if test="businessKey != null and businessKey != ''">and business_key = #{businessKey}</if> <if test="businessKey != null and businessKey != ''">and business_key = #{businessKey}</if>
@ -109,6 +113,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="extendField2 != null and extendField2 != ''">and extend_field2 like <if test="extendField2 != null and extendField2 != ''">and extend_field2 like
concat('%',#{extendField2},'%') concat('%',#{extendField2},'%')
</if> </if>
<if test="extendField3 != null and extendField3 != ''">and extend_field3 like
concat('%',#{extendField3},'%')
</if>
<if test="processInstanceId != null and processInstanceId != ''">and process_instance_id = <if test="processInstanceId != null and processInstanceId != ''">and process_instance_id =
#{processInstanceId} #{processInstanceId}
</if> </if>
@ -146,6 +153,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="todoId != null and todoId != ''"> and todo_id = #{todoId}</if> <if test="todoId != null and todoId != ''"> and todo_id = #{todoId}</if>
</where> </where>
</select> </select>
<select id="selectFirstCompletedByProcessInstanceId" resultType="com.ruoyi.sip.flowable.domain.Todo">
<include refid="selectTodoCompletedVo" />
where process_instance_id = #{processInstanceId}
order by id asc
limit 1
</select>
<select id="selectTodo" resultType="com.ruoyi.sip.flowable.domain.Todo"> <select id="selectTodo" resultType="com.ruoyi.sip.flowable.domain.Todo">
<include refid="selectTodoVo"/> <include refid="selectTodoVo"/>
<where> <where>
@ -160,6 +173,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="applyTime != null "> and apply_time like concat(date_format(#{applyTime},'%y-%m-%d'),'%')</if> <if test="applyTime != null "> and apply_time like concat(date_format(#{applyTime},'%y-%m-%d'),'%')</if>
<if test="extendField1 != null and extendField1 != ''"> and extend_field1 like concat('%',#{extendField1},'%')</if> <if test="extendField1 != null and extendField1 != ''"> and extend_field1 like concat('%',#{extendField1},'%')</if>
<if test="extendField2 != null and extendField2 != ''"> and extend_field2 like concat('%',#{extendField2},'%')</if> <if test="extendField2 != null and extendField2 != ''"> and extend_field2 like concat('%',#{extendField2},'%')</if>
<if test="extendField3 != null and extendField3 != ''"> and extend_field3 like concat('%',#{extendField3},'%')</if>
<if test="processInstanceId != null and processInstanceId != ''"> and process_instance_id = #{processInstanceId}</if> <if test="processInstanceId != null and processInstanceId != ''"> and process_instance_id = #{processInstanceId}</if>
<if test="taskId != null and taskId != ''"> and task_id = #{taskId}</if> <if test="taskId != null and taskId != ''"> and task_id = #{taskId}</if>
</where> </where>
@ -168,7 +182,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectGQOrYQCompletedList" resultType="com.ruoyi.sip.flowable.domain.Todo"> <select id="selectGQOrYQCompletedList" resultType="com.ruoyi.sip.flowable.domain.Todo">
select todo_id, business_key, process_key, process_name, task_name, select todo_id, business_key, process_key, process_name, task_name,
approve_user_name,approve_time,approve_opinion, approve_user_name,approve_time,approve_opinion,
approve_status,apply_user_name, apply_time, extend_field1, extend_field2,task_id,process_instance_id,form_key approve_status,apply_user_name, apply_time, extend_field1, extend_field2,extend_field3,task_id,process_instance_id,form_key
from bu_todo_completed from bu_todo_completed
where form_key in ('work_order_001','work_order_006') where form_key in ('work_order_001','work_order_006')
<if test="businessKey != null and businessKey != ''">and business_key = #{businessKey}</if> <if test="businessKey != null and businessKey != ''">and business_key = #{businessKey}</if>
@ -190,6 +204,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="applyTime != null">apply_time,</if> <if test="applyTime != null">apply_time,</if>
<if test="extendField1 != null">extend_field1,</if> <if test="extendField1 != null">extend_field1,</if>
<if test="extendField2 != null">extend_field2,</if> <if test="extendField2 != null">extend_field2,</if>
<if test="extendField3 != null">extend_field3,</if>
<if test="taskId != null">task_id,</if> <if test="taskId != null">task_id,</if>
<if test="processInstanceId != null">process_instance_id,</if> <if test="processInstanceId != null">process_instance_id,</if>
<if test="formKey != null">form_key,</if> <if test="formKey != null">form_key,</if>
@ -206,6 +221,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="applyTime != null">#{applyTime},</if> <if test="applyTime != null">#{applyTime},</if>
<if test="extendField1 != null">#{extendField1},</if> <if test="extendField1 != null">#{extendField1},</if>
<if test="extendField2 != null">#{extendField2},</if> <if test="extendField2 != null">#{extendField2},</if>
<if test="extendField3 != null">#{extendField3},</if>
<if test="taskId != null">#{taskId},</if> <if test="taskId != null">#{taskId},</if>
<if test="processInstanceId != null">#{processInstanceId},</if> <if test="processInstanceId != null">#{processInstanceId},</if>
<if test="formKey != null">#{formKey},</if> <if test="formKey != null">#{formKey},</if>
@ -214,7 +230,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<insert id="insertTodoCompleted"> <insert id="insertTodoCompleted">
insert into bu_todo_completed insert into bu_todo_completed
( todo_id, business_key, process_key, process_name, task_name, approve_user, approve_user_name, apply_user_name, apply_time, extend_field1,extend_field2, task_id, ( todo_id, business_key, process_key, process_name, task_name, approve_user, approve_user_name, apply_user_name, apply_time, extend_field1,extend_field2,extend_field3, task_id,
process_instance_id,approve_time,approve_opinion,approve_status,form_key,all_approve_user_name ) values process_instance_id,approve_time,approve_opinion,approve_status,form_key,all_approve_user_name ) values
<foreach collection="list" item="d" open="(" close=")" separator="," > <foreach collection="list" item="d" open="(" close=")" separator="," >
#{d.todoId}, #{d.todoId},
@ -228,6 +244,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{d.applyTime}, #{d.applyTime},
#{d.extendField1}, #{d.extendField1},
#{d.extendField2}, #{d.extendField2},
#{d.extendField3},
#{d.taskId}, #{d.taskId},
#{d.processInstanceId}, #{d.processInstanceId},
#{d.approveTime}, #{d.approveTime},
@ -251,6 +268,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="applyTime != null">apply_time = #{applyTime},</if> <if test="applyTime != null">apply_time = #{applyTime},</if>
<if test="extendField1 != null">extend_field1 = #{extendField1},</if> <if test="extendField1 != null">extend_field1 = #{extendField1},</if>
<if test="extendField2 != null">extend_field2 = #{extendField2},</if> <if test="extendField2 != null">extend_field2 = #{extendField2},</if>
<if test="extendField3 != null">extend_field3 = #{extendField3},</if>
</trim> </trim>
where id = #{id} where id = #{id}
</update> </update>

View File

@ -13,16 +13,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="deliveryTimeType" column="delivery_time_type" /> <result property="deliveryTimeType" column="delivery_time_type" />
<result property="deliveryTime" column="delivery_time" /> <result property="deliveryTime" column="delivery_time" />
<result property="deliveryStatus" column="delivery_status" /> <result property="deliveryStatus" column="delivery_status" />
<result property="approveStatus" column="approve_status" />
<result property="deliveryType" column="delivery_type" /> <result property="deliveryType" column="delivery_type" />
<result property="createBy" column="create_by" /> <result property="createBy" column="create_by" />
<result property="createTime" column="create_time" /> <result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" /> <result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" /> <result property="updateTime" column="update_time" />
<result property="versionCode" column="version_code" />
</resultMap> </resultMap>
<sql id="selectInventoryDeliveryVo"> <sql id="selectInventoryDeliveryVo">
select t1.id, t1.outer_code, t1.warehouse_id,t1.quantity, t1.logistics_company,t1.delivery_status, t1.logistics_code,t1.remark select t1.id, t1.outer_code, t1.warehouse_id,t1.quantity, t1.logistics_company,t1.delivery_status, t1.approve_status, t1.logistics_code,t1.remark
, t1.delivery_time_type, t1.delivery_time, t1.delivery_type, t1.create_by, t1.create_time, t1.update_by, t1.update_time , t1.delivery_time_type, t1.delivery_time, t1.delivery_type, t1.create_by, t1.create_time, t1.update_by, t1.update_time
, t1.version_code
,t2.warehouse_name, ,t2.warehouse_name,
t5.project_code, t5.project_name, t5.project_code, t5.project_name,
t4.order_code,t4.notifier_address, t4.order_code,t4.notifier_address,
@ -41,13 +44,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectInventoryDeliveryList" parameterType="InventoryDelivery" resultMap="InventoryDeliveryResult"> <select id="selectInventoryDeliveryList" parameterType="InventoryDelivery" resultMap="InventoryDeliveryResult">
<include refid="selectInventoryDeliveryVo"/> <include refid="selectInventoryDeliveryVo"/>
<where> <where>
and t1.delivery_status != 2 <!-- 默认排除已撤回记录;显式指定状态查询时(如查看已撤回记录)不排除 -->
<if test="deliveryStatus == null or deliveryStatus == ''">and t1.delivery_status != 2</if>
<if test="deliveryStatus != null and deliveryStatus != ''">and t1.delivery_status = #{deliveryStatus}</if>
<if test="outerCode != null and outerCode != ''">and t1.outer_code = #{outerCode}</if> <if test="outerCode != null and outerCode != ''">and t1.outer_code = #{outerCode}</if>
<if test="warehouseId != null ">and t1.warehouse_id = #{warehouseId}</if> <if test="warehouseId != null ">and t1.warehouse_id = #{warehouseId}</if>
<if test="logisticsCompany != null and logisticsCompany != ''">and t1.logistics_company = <if test="logisticsCompany != null and logisticsCompany != ''">and t1.logistics_company =
#{logisticsCompany} #{logisticsCompany}
</if> </if>
<if test="deliveryStatus != null and deliveryStatus != ''">and t1.delivery_status = #{deliveryStatus}</if>
<if test="logisticsCode != null and logisticsCode != ''">and t1.logistics_code = #{logisticsCode}</if> <if test="logisticsCode != null and logisticsCode != ''">and t1.logistics_code = #{logisticsCode}</if>
<if test="deliveryTimeType != null and deliveryTimeType != ''">and t1.delivery_time_type = <if test="deliveryTimeType != null and deliveryTimeType != ''">and t1.delivery_time_type =
#{deliveryTimeType} #{deliveryTimeType}
@ -143,6 +147,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateBy != null">update_by,</if> <if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if> <if test="updateTime != null">update_time,</if>
<if test="remark != null and remark!=''">remark,</if> <if test="remark != null and remark!=''">remark,</if>
<if test="versionCode != null">version_code,</if>
</trim> </trim>
<trim prefix="values (" suffix=")" suffixOverrides=","> <trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="outerCode != null">#{outerCode},</if> <if test="outerCode != null">#{outerCode},</if>
@ -159,6 +164,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateBy != null">#{updateBy},</if> <if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if> <if test="updateTime != null">#{updateTime},</if>
<if test="remark != null and remark!=''">#{remark},</if> <if test="remark != null and remark!=''">#{remark},</if>
<if test="versionCode != null">#{versionCode},</if>
</trim> </trim>
</insert> </insert>
@ -170,6 +176,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="quantity != null">quantity=#{quantity},</if> <if test="quantity != null">quantity=#{quantity},</if>
<if test="logisticsCompany != null">logistics_company = #{logisticsCompany},</if> <if test="logisticsCompany != null">logistics_company = #{logisticsCompany},</if>
<if test="deliveryStatus != null and deliveryStatus != ''">delivery_status = #{deliveryStatus},</if> <if test="deliveryStatus != null and deliveryStatus != ''">delivery_status = #{deliveryStatus},</if>
<if test="approveStatus != null and approveStatus != ''">approve_status = #{approveStatus},</if>
<if test="logisticsCode != null">logistics_code = #{logisticsCode},</if> <if test="logisticsCode != null">logistics_code = #{logisticsCode},</if>
<if test="deliveryTimeType != null">delivery_time_type = #{deliveryTimeType},</if> <if test="deliveryTimeType != null">delivery_time_type = #{deliveryTimeType},</if>
<if test="deliveryTime != null">delivery_time = #{deliveryTime},</if> <if test="deliveryTime != null">delivery_time = #{deliveryTime},</if>

View File

@ -24,7 +24,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectInventoryInfoVo"> <sql id="selectInventoryInfoVo">
select t1.id, t1.product_code, t1.product_sn, t1.license_key, t1.inventory_status, t1.inner_code, t1.outer_code, t1.order_code, t1.warehouse_id, t1.inner_price,t1.tax_rate, select t1.id, t1.product_code, t1.product_sn, t1.license_key, t1.inventory_status, t1.inner_code, t1.outer_code, t1.order_code, t1.warehouse_id, t1.inner_price,t1.tax_rate,
t1.outer_price, t1.create_by, t1.create_time, t1.update_by, t1.update_time , t1.outer_price, t1.create_by, t1.create_time, t1.update_by, t1.update_time, t1.payable_bill_code,
t2.warehouse_name,t3.description as 'product_desc',t3.model,t3.type as product_type t2.warehouse_name,t3.description as 'product_desc',t3.model,t3.type as product_type
from oms_inventory_info t1 from oms_inventory_info t1
left join oms_warehouse_info t2 on t1.warehouse_id = t2.id left join oms_warehouse_info t2 on t1.warehouse_id = t2.id
@ -193,6 +193,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
inventory_status = VALUES(inventory_status), inventory_status = VALUES(inventory_status),
outer_code = VALUES(outer_code), outer_code = VALUES(outer_code),
outer_price = VALUES(outer_price), outer_price = VALUES(outer_price),
payable_bill_code = VALUES(payable_bill_code),
update_by = VALUES(update_by), update_by = VALUES(update_by),
update_time = now(), update_time = now(),
order_code = VALUES(order_code) order_code = VALUES(order_code)
@ -270,6 +271,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach> </foreach>
</update> </update>
<update id="clearPayableBillCodeByIds">
update oms_inventory_info
set payable_bill_code = null,
update_time = now()
where id in
<foreach item="id" collection="idList" separator="," open="(" close=")">
#{id}
</foreach>
</update>
<delete id="deleteInventoryInfoById" parameterType="Long"> <delete id="deleteInventoryInfoById" parameterType="Long">
delete from oms_inventory_info where id = #{id} delete from oms_inventory_info where id = #{id}
</delete> </delete>

View File

@ -20,6 +20,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateBy" column="update_by" /> <result property="updateBy" column="update_by" />
<result property="createTime" column="create_time" /> <result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" /> <result property="updateTime" column="update_time" />
<result property="versionCode" column="version_code" />
</resultMap> </resultMap>
<sql id="selectInventoryOuterVo"> <sql id="selectInventoryOuterVo">
@ -58,6 +59,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.create_time, t1.create_time,
t1.update_time, t1.update_time,
t1.delivery_status, t1.delivery_status,
t1.version_code,
t2.model, t2.model,
t3.id as order_id, t3.id as order_id,
t3.project_id, t3.project_id,
@ -107,6 +109,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="contactPerson != null and contactPerson != ''">and t1.contact_person = #{contactPerson}</if> <if test="contactPerson != null and contactPerson != ''">and t1.contact_person = #{contactPerson}</if>
<if test="contactPhone != null and contactPhone != ''">and t1.contact_phone = #{contactPhone}</if> <if test="contactPhone != null and contactPhone != ''">and t1.contact_phone = #{contactPhone}</if>
<if test="deliveryStatus != null and deliveryStatus != ''">and t1.delivery_status = #{deliveryStatus}</if> <if test="deliveryStatus != null and deliveryStatus != ''">and t1.delivery_status = #{deliveryStatus}</if>
<if test="excludeRecalled">and t1.delivery_status != '3'</if>
<if test="contactAddress != null and contactAddress != ''">and t1.contact_address = #{contactAddress}</if> <if test="contactAddress != null and contactAddress != ''">and t1.contact_address = #{contactAddress}</if>
<if test="deliveryTime != null ">and t1.delivery_time = #{deliveryTime}</if> <if test="deliveryTime != null ">and t1.delivery_time = #{deliveryTime}</if>
<if test="warehouseId != null ">and t1.outer_code in (select outer_code from oms_inventory_outer_detail <if test="warehouseId != null ">and t1.outer_code in (select outer_code from oms_inventory_outer_detail
@ -155,6 +158,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select count(1) select count(1)
from oms_inventory_outer from oms_inventory_outer
where order_code = #{orderCode} where order_code = #{orderCode}
and delivery_status != '3'
</select> </select>
<select id="selectInventoryOuterByCode" resultType="com.ruoyi.sip.domain.InventoryOuter"> <select id="selectInventoryOuterByCode" resultType="com.ruoyi.sip.domain.InventoryOuter">
<include refid="selectInventoryOuterRelationVo"/> <include refid="selectInventoryOuterRelationVo"/>
@ -221,6 +225,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="outerStatus != null">outer_status,</if> <if test="outerStatus != null">outer_status,</if>
<if test="deliveryStatus != null and deliveryStatus!=''">delivery_status,</if> <if test="deliveryStatus != null and deliveryStatus!=''">delivery_status,</if>
<if test="orderCode != null">order_code,</if> <if test="orderCode != null">order_code,</if>
<if test="versionCode != null">version_code,</if>
<if test="contactPerson != null">contact_person,</if> <if test="contactPerson != null">contact_person,</if>
<if test="contactPhone != null">contact_phone,</if> <if test="contactPhone != null">contact_phone,</if>
<if test="contactAddress != null">contact_address,</if> <if test="contactAddress != null">contact_address,</if>
@ -238,6 +243,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="outerStatus != null">#{outerStatus},</if> <if test="outerStatus != null">#{outerStatus},</if>
<if test="deliveryStatus != null and deliveryStatus!=''">#{deliveryStatus},</if> <if test="deliveryStatus != null and deliveryStatus!=''">#{deliveryStatus},</if>
<if test="orderCode != null">#{orderCode},</if> <if test="orderCode != null">#{orderCode},</if>
<if test="versionCode != null">#{versionCode},</if>
<if test="contactPerson != null">#{contactPerson},</if> <if test="contactPerson != null">#{contactPerson},</if>
<if test="contactPhone != null">#{contactPhone},</if> <if test="contactPhone != null">#{contactPhone},</if>
<if test="contactAddress != null">#{contactAddress},</if> <if test="contactAddress != null">#{contactAddress},</if>
@ -272,6 +278,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where id = #{id} where id = #{id}
</update> </update>
<update id="updateDeliveryStatusByOuterCode">
update oms_inventory_outer
set delivery_status = #{deliveryStatus}
where outer_code = #{outerCode}
</update>
<delete id="deleteInventoryOuterById" parameterType="Long"> <delete id="deleteInventoryOuterById" parameterType="Long">
delete from oms_inventory_outer where id = #{id} delete from oms_inventory_outer where id = #{id}
</delete> </delete>

View File

@ -49,6 +49,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="paymentDescription" column="payment_description" /> <result property="paymentDescription" column="payment_description" />
<result property="operationVersion" column="operation_version" /> <result property="operationVersion" column="operation_version" />
<result property="orderStockingStatus" column="order_stocking_status" /> <result property="orderStockingStatus" column="order_stocking_status" />
<result property="rebackApproveStatus" column="reback_approve_status" />
</resultMap> </resultMap>
<sql id="selectProjectOrderInfoVo"> <sql id="selectProjectOrderInfoVo">
@ -56,7 +57,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
shipment_amount, actual_purchase_amount, order_end_time, delivery_time, company_delivery, notifier,finance_status, shipment_amount, actual_purchase_amount, order_end_time, delivery_time, company_delivery, notifier,finance_status,
notifier_email, notifier_phone, duty, duty_email, duty_phone, order_channel, partner_code, supplier,notifier_address, notifier_email, notifier_phone, duty, duty_email, duty_phone, order_channel, partner_code, supplier,notifier_address,
remark, order_status, create_by, create_time, update_by, update_time,version_code,process_type,process_template,discount_fold,order_stocking_status, remark, order_status, create_by, create_time, update_by, update_time,version_code,process_type,process_template,discount_fold,order_stocking_status,
delivery_status,sign_status,outer_status,approve_time,payment_method,payment_ratio,payment_description,order_type,operation_version delivery_status,sign_status,outer_status,approve_time,payment_method,payment_ratio,payment_description,order_type,operation_version,reback_approve_status
from project_order_info t1 from project_order_info t1
</sql> </sql>
@ -66,7 +67,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.notifier_email, t1.notifier_phone, t1.duty, t1.duty_email, t1.duty_phone, t1.order_channel, t1.partner_code, t1.supplier, t1.notifier_email, t1.notifier_phone, t1.duty, t1.duty_email, t1.duty_phone, t1.order_channel, t1.partner_code, t1.supplier,
t1.remark, t1.order_status, t1.create_by, t1.create_time, t1.update_by, t1.update_time,t1.partner_user_name,t1.partner_email t1.remark, t1.order_status, t1.create_by, t1.create_time, t1.update_by, t1.update_time,t1.partner_user_name,t1.partner_email
,t1.partner_phone,t1.version_code,t1.process_type,t1.process_template,t1.discount_fold,t1.notifier_address,t1.finance_status, ,t1.partner_phone,t1.version_code,t1.process_type,t1.process_template,t1.discount_fold,t1.notifier_address,t1.finance_status,
t1.delivery_status,t1.sign_status,t1.outer_status,t1.approve_time,t1.payment_method,t1.payment_ratio,t1.payment_description,t1.operation_version,t1.order_stocking_status t1.delivery_status,t1.sign_status,t1.outer_status,t1.approve_time,t1.payment_method,t1.payment_ratio,t1.payment_description,t1.operation_version,t1.order_stocking_status,t1.reback_approve_status
,t2.project_code,t2.project_name,t2.project_desc,t2.software_info,t2.hardware_info,t2.terminal_peripheral,t2.server_configuration ,t2.project_code,t2.project_name,t2.project_desc,t2.software_info,t2.hardware_info,t2.terminal_peripheral,t2.server_configuration
,t2.management_version,t2.desktop_vm_os_version,t2.vm_spec_quantity,t2.key_problem,t2.joint_trial_result ,t2.management_version,t2.desktop_vm_os_version,t2.vm_spec_quantity,t2.key_problem,t2.joint_trial_result
,t2.province,t2.customer_name,t2.customer_code,t2.industry_type,t2.bg_property,t2.agent_code,t2.estimated_order_time ,t2.province,t2.customer_name,t2.customer_code,t2.industry_type,t2.bg_property,t2.agent_code,t2.estimated_order_time
@ -134,7 +135,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if> </if>
<if test="supplier != null and supplier != ''">and t1.supplier = #{supplier}</if> <if test="supplier != null and supplier != ''">and t1.supplier = #{supplier}</if>
<if test="supplier != null and supplier != ''">and t1.supplier = #{supplier}</if> <if test="supplier != null and supplier != ''">and t1.supplier = #{supplier}</if>
<if test="orderStatus != null and orderStatus != ''">and t1.order_status = #{orderStatus}</if> <if test="orderStatus != null and orderStatus != ''">and (t1.order_status = #{orderStatus} or t1.reback_approve_status is not null)</if>
<if test="orderStockingStatus != null and orderStockingStatus != ''">and t1.order_stocking_status = #{orderStockingStatus}</if> <if test="orderStockingStatus != null and orderStockingStatus != ''">and t1.order_stocking_status = #{orderStockingStatus}</if>
<if test="deliveryStatus != null and deliveryStatus != ''">and t1.delivery_status = #{deliveryStatus}</if> <if test="deliveryStatus != null and deliveryStatus != ''">and t1.delivery_status = #{deliveryStatus}</if>
<if test="outerStatus != null and outerStatus != ''">and t1.outer_status = #{outerStatus}</if> <if test="outerStatus != null and outerStatus != ''">and t1.outer_status = #{outerStatus}</if>
@ -836,10 +837,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="paymentRatio != null">payment_ratio = #{paymentRatio},</if> <if test="paymentRatio != null">payment_ratio = #{paymentRatio},</if>
<if test="paymentDescription != null and paymentDescription != ''">payment_description = #{paymentDescription},</if> <if test="paymentDescription != null and paymentDescription != ''">payment_description = #{paymentDescription},</if>
<if test="financeStatus != null and financeStatus != ''">finance_status = #{financeStatus},</if> <if test="financeStatus != null and financeStatus != ''">finance_status = #{financeStatus},</if>
<if test="rebackApproveStatus != null and rebackApproveStatus != ''">reback_approve_status = #{rebackApproveStatus},</if>
<if test="operationVersion != null">operation_version = #{operationVersion},</if> <if test="operationVersion != null">operation_version = #{operationVersion},</if>
</trim> </trim>
where id = #{id} where id = #{id}
</update> </update>
<update id="clearRebackApproveStatus" parameterType="Long">
update project_order_info
set reback_approve_status = null
where id = #{id}
</update>
<update id="updateProjectOrderInfoByCode" parameterType="ProjectOrderInfo"> <update id="updateProjectOrderInfoByCode" parameterType="ProjectOrderInfo">
update project_order_info update project_order_info
<trim prefix="SET" suffixOverrides=","> <trim prefix="SET" suffixOverrides=",">