Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
M
mini-wms
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Members
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
周海峰
mini-wms
Commits
15102e6e
Commit
15102e6e
authored
Dec 05, 2025
by
yubin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
出库
parent
389f53a1
隐藏空白字符变更
内嵌
并排
正在显示
25 个修改的文件
包含
1031 行增加
和
451 行删除
+1031
-451
ruoyi-admin-vue/src/api/inventory/inventory.js
+9
-0
ruoyi-admin-vue/src/api/inventory/orders.js
+9
-0
ruoyi-admin-vue/src/views/inventory/orders/OutboundOrderFormWithItems.vue
+204
-214
ruoyi-admin-vue/src/views/inventory/orders/index.vue
+279
-112
ruoyi-admin/src/main/java/com/ruoyi/web/controller/inventory/InboundOrderItemsController.java
+1
-2
ruoyi-common/pom.xml
+4
-0
ruoyi-common/src/main/java/com/ruoyi/common/annotation/SerialExecution.java
+25
-0
ruoyi-common/src/main/java/com/ruoyi/common/aspectj/SerialExecutionAspect.java
+72
-0
ruoyi-inventory/src/main/java/com/ruoyi/inventory/controller/OutboundOrderItemsController.java
+21
-2
ruoyi-inventory/src/main/java/com/ruoyi/inventory/controller/OutboundOrdersController.java
+13
-0
ruoyi-inventory/src/main/java/com/ruoyi/inventory/domain/OutboundOrderItems.java
+14
-1
ruoyi-inventory/src/main/java/com/ruoyi/inventory/domain/OutboundOrderLog.java
+13
-1
ruoyi-inventory/src/main/java/com/ruoyi/inventory/mapper/InventoryMapper.java
+3
-1
ruoyi-inventory/src/main/java/com/ruoyi/inventory/mapper/OutboundOrderLogMapper.java
+23
-1
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/IInventoryService.java
+20
-9
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/IOutboundOrderLogService.java
+0
-1
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/IOutboundOrdersService.java
+9
-0
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/InventoryServiceImpl.java
+82
-16
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/OutboundOrderItemsServiceImpl.java
+2
-16
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/OutboundOrderLogServiceImpl.java
+0
-4
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/OutboundOrdersServiceImpl.java
+104
-21
ruoyi-inventory/src/main/resources/mapper/inventory/InventoryMapper.xml
+9
-2
ruoyi-inventory/src/main/resources/mapper/inventory/OutboundOrderItemsMapper.xml
+6
-1
ruoyi-inventory/src/main/resources/mapper/inventory/OutboundOrderLogMapper.xml
+58
-9
ruoyi-inventory/src/main/resources/mapper/inventory/OutboundOrdersMapper.xml
+51
-38
没有找到文件。
ruoyi-admin-vue/src/api/inventory/inventory.js
View file @
15102e6e
...
@@ -68,3 +68,12 @@ export function listInventoryByMaterialId(materialId) {
...
@@ -68,3 +68,12 @@ export function listInventoryByMaterialId(materialId) {
params
:
{
materialId
:
materialId
}
params
:
{
materialId
:
materialId
}
})
})
}
}
export
function
Ship
(
data
)
{
return
request
({
url
:
'/inventory/inventory/ship'
,
method
:
'post'
,
data
:
data
})
}
ruoyi-admin-vue/src/api/inventory/orders.js
View file @
15102e6e
...
@@ -51,3 +51,11 @@ export function listWarehouseInventory(warehouseId) {
...
@@ -51,3 +51,11 @@ export function listWarehouseInventory(warehouseId) {
params
:
{
warehouseId
:
warehouseId
}
params
:
{
warehouseId
:
warehouseId
}
})
})
}
}
export
function
ship
(
data
)
{
return
request
({
url
:
'/inventory/orders/ship'
,
method
:
'post'
,
data
:
data
})
}
\ No newline at end of file
ruoyi-admin-vue/src/views/inventory/orders/OutboundOrderFormWithItems.vue
View file @
15102e6e
...
@@ -66,7 +66,7 @@
...
@@ -66,7 +66,7 @@
</el-col>
</el-col>
</el-row>
</el-row>
<!-- 库存信息列表 -->
<!-- 库存信息列表 -
添加库存ID列 -
->
<el-row
v-if=
"form.materialId && form.materialId.trim()"
style=
"margin: 10px 0;"
>
<el-row
v-if=
"form.materialId && form.materialId.trim()"
style=
"margin: 10px 0;"
>
<el-col
:span=
"24"
>
<el-col
:span=
"24"
>
<div
style=
"margin-bottom: 8px; font-weight: 600; color: #1989fa;"
>
<div
style=
"margin-bottom: 8px; font-weight: 600; color: #1989fa;"
>
...
@@ -81,11 +81,10 @@
...
@@ -81,11 +81,10 @@
highlight-current-row
highlight-current-row
stripe
stripe
empty-text=
"暂无库存数据"
empty-text=
"暂无库存数据"
@
selection-change=
"handleSelectionChange"
@
row-click=
"handleRowClick"
@
row-click=
"handleRowClick"
:row-key=
"item => item.id"
>
>
<el-table-column
type=
"selection"
width=
"55"
/>
<el-table-column
prop=
"id"
label=
"库存ID"
width=
"100"
/>
<el-table-column
prop=
"id"
label=
"库存ID"
width=
"100"
/>
<el-table-column
prop=
"materialId"
label=
"货物ID"
width=
"100"
/>
<el-table-column
prop=
"materialId"
label=
"货物ID"
width=
"100"
/>
<el-table-column
prop=
"batchId"
label=
"批次ID"
width=
"100"
/>
<el-table-column
prop=
"batchId"
label=
"批次ID"
width=
"100"
/>
<el-table-column
prop=
"orderId"
label=
"订单ID"
width=
"120"
/>
<el-table-column
prop=
"orderId"
label=
"订单ID"
width=
"120"
/>
...
@@ -107,31 +106,20 @@
...
@@ -107,31 +106,20 @@
{{
(
scope
.
row
.
quantity
||
0
)
-
(
scope
.
row
.
lockedQuantity
||
0
)
}}
{{
(
scope
.
row
.
quantity
||
0
)
-
(
scope
.
row
.
lockedQuantity
||
0
)
}}
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"选择数量"
width=
"120"
>
<!-- 实际数量:填写即视为选中(原选择数量) -->
<el-table-column
label=
"实际数量"
width=
"120"
>
<
template
slot-scope=
"scope"
>
<
template
slot-scope=
"scope"
>
<el-input
<el-input
v-model
.
number=
"scope.row.
selectedQ
ty"
v-model
.
number=
"scope.row.
actualQuanti
ty"
type=
"number"
type=
"number"
size=
"mini"
size=
"mini"
min=
"1"
min=
"1"
:max=
"(scope.row.quantity || 0) - (scope.row.lockedQuantity || 0)"
:max=
"(scope.row.quantity || 0) - (scope.row.lockedQuantity || 0)"
@
input=
"handleRow
QtyInput(scope.row
)"
@
input=
"handleRow
ActualQtyInput(scope.row); syncDetails(
)"
placeholder=
"输入数量"
placeholder=
"输入数量"
/>
/>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"计划件数"
width=
"120"
>
<
template
slot-scope=
"scope"
>
<el-input
v-model
.
number=
"scope.row.plannedPackages"
type=
"number"
size=
"mini"
min=
"0"
@
input=
"handleRowPackagesInput(scope.row)"
placeholder=
"输入件数"
/>
</
template
>
</el-table-column>
</el-table>
</el-table>
<!-- 选中行的扩展字段填写区域 -->
<!-- 选中行的扩展字段填写区域 -->
...
@@ -140,8 +128,9 @@
...
@@ -140,8 +128,9 @@
style=
"margin-top: 10px; padding: 10px; border: 1px solid #e6e6e6; border-radius: 4px;"
style=
"margin-top: 10px; padding: 10px; border: 1px solid #e6e6e6; border-radius: 4px;"
>
>
<div
style=
"margin-bottom: 8px; font-weight: 600; color: #1989fa;"
>
<div
style=
"margin-bottom: 8px; font-weight: 600; color: #1989fa;"
>
库存
【ID: {{ currentSelectedRow.id }}】
明细信息
库存明细信息
</div>
</div>
<!-- 扩展字段区域保持不变 -->
<el-row
:gutter=
"20"
>
<el-row
:gutter=
"20"
>
<el-col
:span=
"8"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"约数"
prop=
"divisor"
>
<el-form-item
label=
"约数"
prop=
"divisor"
>
...
@@ -150,12 +139,13 @@
...
@@ -150,12 +139,13 @@
placeholder=
"请输入约数"
placeholder=
"请输入约数"
type=
"number"
type=
"number"
min=
"0"
min=
"0"
@
input=
"syncDetails()"
/>
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"8"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"标签颜色"
prop=
"labelColor"
>
<el-form-item
label=
"标签颜色"
prop=
"labelColor"
>
<el-select
v-model=
"currentSelectedRow.labelColor"
placeholder=
"请选择标签颜色"
>
<el-select
v-model=
"currentSelectedRow.labelColor"
placeholder=
"请选择标签颜色"
@
change=
"syncDetails()"
>
<el-option
label=
"红色"
value=
"1"
></el-option>
<el-option
label=
"红色"
value=
"1"
></el-option>
<el-option
label=
"蓝色"
value=
"2"
></el-option>
<el-option
label=
"蓝色"
value=
"2"
></el-option>
<el-option
label=
"绿色"
value=
"3"
></el-option>
<el-option
label=
"绿色"
value=
"3"
></el-option>
...
@@ -163,35 +153,26 @@
...
@@ -163,35 +153,26 @@
</el-select>
</el-select>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"8"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"
单价"
prop=
"unitPrice
"
>
<el-form-item
label=
"
计划数量"
prop=
"plannedQuantity
"
>
<el-input
<el-input
v-model
.
number=
"currentSelectedRow.unitPrice"
v-model
.
number=
"currentSelectedRow.plannedQuantity"
placeholder=
"请输入单价"
type=
"number"
type=
"number"
min=
"0"
min=
"1"
step=
"0.01"
:max=
"(currentSelectedRow.quantity || 0) - (currentSelectedRow.lockedQuantity || 0)"
@
input=
"handleRowPlannedQtyInput(currentSelectedRow); syncDetails()"
placeholder=
"输入计划数量"
/>
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row
:gutter=
"20"
style=
"margin-top: 10px;"
>
<el-row
:gutter=
"20"
style=
"margin-top: 10px;"
>
<el-col
:span=
"12"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"收货时间"
prop=
"receivedAt"
>
<el-form-item
label=
"发货方"
prop=
"shippedBy"
>
<el-date-picker
v-model=
"currentSelectedRow.receivedAt"
type=
"datetime"
value-format=
"yyyy-MM-dd HH:mm:ss"
placeholder=
"请选择收货时间"
style=
"width: 100%"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"收货人"
prop=
"receivedBy"
>
<el-input
<el-input
v-model=
"currentSelectedRow.receivedBy"
v-model=
"currentSelectedRow.shippedBy"
placeholder=
"请输入收货人"
placeholder=
"请输入发货方"
@
input=
"syncDetails()"
/>
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
...
@@ -202,6 +183,7 @@
...
@@ -202,6 +183,7 @@
<el-input
<el-input
v-model=
"currentSelectedRow.voucherNumber"
v-model=
"currentSelectedRow.voucherNumber"
placeholder=
"请输入凭证号"
placeholder=
"请输入凭证号"
@
input=
"syncDetails()"
/>
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
...
@@ -214,6 +196,7 @@
...
@@ -214,6 +196,7 @@
placeholder=
"请输入备注"
placeholder=
"请输入备注"
type=
"textarea"
type=
"textarea"
rows=
"2"
rows=
"2"
@
input=
"syncDetails()"
/>
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
...
@@ -222,7 +205,7 @@
...
@@ -222,7 +205,7 @@
</el-col>
</el-col>
</el-row>
</el-row>
<!-- 已生成的明细预览 -->
<!-- 已生成的明细预览 -
添加库存ID列 -
->
<el-row
v-if=
"details.length > 0"
style=
"margin: 10px 0;"
>
<el-row
v-if=
"details.length > 0"
style=
"margin: 10px 0;"
>
<el-col
:span=
"24"
>
<el-col
:span=
"24"
>
<div
style=
"margin-bottom: 8px; font-weight: 600; color: #1989fa;"
>
<div
style=
"margin-bottom: 8px; font-weight: 600; color: #1989fa;"
>
...
@@ -233,24 +216,22 @@
...
@@ -233,24 +216,22 @@
border
border
size=
"small"
size=
"small"
max-height=
"200"
max-height=
"200"
:row-key=
"item => item.inventoryId"
>
>
<el-table-column
prop=
"batchId"
label=
"批次ID"
/>
<el-table-column
prop=
"inventoryId"
label=
"库存ID"
width=
"100"
/>
<el-table-column
prop=
"batchCode"
label=
"批次ID"
/>
<el-table-column
prop=
"warehouseId"
label=
"仓库ID"
/>
<el-table-column
prop=
"warehouseId"
label=
"仓库ID"
/>
<el-table-column
prop=
"locationId"
label=
"库位ID"
/>
<el-table-column
prop=
"locationId"
label=
"库位ID"
/>
<el-table-column
prop=
"plannedQuantity"
label=
"计划数量"
/>
<el-table-column
prop=
"plannedQuantity"
label=
"计划数量"
/>
<el-table-column
prop=
"actualQuantity"
label=
"实际数量"
/>
<el-table-column
prop=
"actualQuantity"
label=
"实际数量"
/>
<el-table-column
prop=
"plannedPackages"
label=
"计划件数"
/>
<el-table-column
prop=
"actualPackages"
label=
"实际件数"
/>
<el-table-column
prop=
"divisor"
label=
"约数"
/>
<el-table-column
prop=
"divisor"
label=
"约数"
/>
<el-table-column
prop=
"unitPrice"
label=
"单价"
/>
<el-table-column
prop=
"labelColor"
label=
"标签颜色"
>
<el-table-column
prop=
"labelColor"
label=
"标签颜色"
>
<
template
slot-scope=
"scope"
>
<
template
slot-scope=
"scope"
>
{{
getLabelColorText
(
scope
.
row
.
labelColor
)
}}
{{
getLabelColorText
(
scope
.
row
.
labelColor
)
}}
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
prop=
"receivedAt"
label=
"收货时间"
/>
<el-table-column
prop=
"receivedBy"
label=
"收货人"
/>
<el-table-column
prop=
"voucherNumber"
label=
"凭证号"
/>
<el-table-column
prop=
"voucherNumber"
label=
"凭证号"
/>
<el-table-column
prop=
"shippedBy"
label=
"发货方"
/>
<el-table-column
prop=
"remark"
label=
"备注"
/>
<el-table-column
prop=
"remark"
label=
"备注"
/>
<el-table-column
label=
"操作"
width=
"80"
>
<el-table-column
label=
"操作"
width=
"80"
>
<
template
slot-scope=
"scope"
>
<
template
slot-scope=
"scope"
>
...
@@ -267,7 +248,7 @@
...
@@ -267,7 +248,7 @@
</el-form>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click
.
native=
"handleClose"
>
取消
</el-button>
<el-button
@
click
.
native=
"handleClose"
>
取消
</el-button>
<el-button
type=
"primary"
@
click
.
native=
"handleSubmit"
>
确定
</el-button>
<el-button
type=
"primary"
@
click
.
native=
"handleSubmit"
>
生成明细
</el-button>
</div>
</div>
</el-dialog>
</el-dialog>
</template>
</template>
...
@@ -276,7 +257,6 @@
...
@@ -276,7 +257,6 @@
import
{
listInventoryByMaterialId
}
from
"@/api/inventory/inventory"
import
{
listInventoryByMaterialId
}
from
"@/api/inventory/inventory"
import
MaterialSelector
from
'../../../components/materialsSeletor.vue'
import
MaterialSelector
from
'../../../components/materialsSeletor.vue'
// 防抖函数(适配Vue2 this上下文)
function
debounce
(
fn
,
delay
=
500
)
{
function
debounce
(
fn
,
delay
=
500
)
{
let
timer
=
null
let
timer
=
null
return
function
(...
args
)
{
return
function
(...
args
)
{
...
@@ -308,14 +288,13 @@ export default {
...
@@ -308,14 +288,13 @@ export default {
},
},
data
()
{
data
()
{
return
{
return
{
// 仅保留全局字段:货物ID、计划总数量
form
:
{
form
:
{
materialUuids
:
''
,
materialUuids
:
''
,
materialId
:
''
,
materialId
:
''
,
totalPlannedQuantity
:
null
,
totalPlannedQuantity
:
null
,
itemStatus
:
'1'
// 对应数据库状态:1-待收货
itemStatus
:
1
},
},
details
:
[],
details
:
[],
inventoryList
:
[],
inventoryList
:
[],
loadingInstance
:
null
,
loadingInstance
:
null
,
rules
:
{
rules
:
{
...
@@ -324,26 +303,11 @@ export default {
...
@@ -324,26 +303,11 @@ export default {
message
:
'请选择货物ID'
,
message
:
'请选择货物ID'
,
trigger
:
[
'change'
,
'blur'
]
trigger
:
[
'change'
,
'blur'
]
}]
}]
// totalPlannedQuantity: [{
// required: true,
// message: '请输入计划总数量',
// trigger: 'blur',
// type: 'number'
// }, {
// validator: (rule, value, callback) => {
// if (value && value
<
1
)
{
// callback(new Error('计划总数量不能小于1'))
// } else {
// callback()
// }
// },
// trigger: 'blur'
// }]
},
},
openMaterialSelector
:
false
,
openMaterialSelector
:
false
,
selectedMaterialId
:
''
,
selectedMaterialId
:
''
,
selectedMaterialInfo
:
null
,
selectedMaterialInfo
:
null
,
currentSelectedRow
:
null
// 存储当前点击的库存行
currentSelectedRow
:
null
}
}
},
},
created
()
{
created
()
{
...
@@ -356,7 +320,7 @@ export default {
...
@@ -356,7 +320,7 @@ export default {
this
.
form
=
{
...
this
.
$options
.
data
().
form
,
...
this
.
initForm
}
this
.
form
=
{
...
this
.
$options
.
data
().
form
,
...
this
.
initForm
}
this
.
selectedMaterialId
=
this
.
form
.
materialId
||
''
this
.
selectedMaterialId
=
this
.
form
.
materialId
||
''
this
.
selectedMaterialInfo
=
null
this
.
selectedMaterialInfo
=
null
this
.
currentSelectedRow
=
null
// 重置选中行
this
.
currentSelectedRow
=
null
if
(
this
.
form
.
materialId
&&
this
.
form
.
materialId
.
trim
())
{
if
(
this
.
form
.
materialId
&&
this
.
form
.
materialId
.
trim
())
{
this
.
handleMaterialIdChange
()
this
.
handleMaterialIdChange
()
}
}
...
@@ -377,7 +341,7 @@ export default {
...
@@ -377,7 +341,7 @@ export default {
this
.
form
=
{
...
this
.
$options
.
data
().
form
,
...
val
}
this
.
form
=
{
...
this
.
$options
.
data
().
form
,
...
val
}
this
.
selectedMaterialId
=
this
.
form
.
materialId
||
''
this
.
selectedMaterialId
=
this
.
form
.
materialId
||
''
this
.
selectedMaterialInfo
=
null
this
.
selectedMaterialInfo
=
null
this
.
currentSelectedRow
=
null
// 重置选中行
this
.
currentSelectedRow
=
null
if
(
this
.
form
.
materialId
&&
this
.
form
.
materialId
.
trim
())
{
if
(
this
.
form
.
materialId
&&
this
.
form
.
materialId
.
trim
())
{
this
.
handleMaterialIdChange
()
this
.
handleMaterialIdChange
()
}
}
...
@@ -388,7 +352,6 @@ export default {
...
@@ -388,7 +352,6 @@ export default {
}
}
},
},
methods
:
{
methods
:
{
// 标签颜色值转文本
getLabelColorText
(
value
)
{
getLabelColorText
(
value
)
{
const
colorMap
=
{
const
colorMap
=
{
'1'
:
'红色'
,
'1'
:
'红色'
,
...
@@ -405,165 +368,152 @@ export default {
...
@@ -405,165 +368,152 @@ export default {
}
}
},
},
async
handleMaterialIdChange
()
{
async
handleMaterialIdChange
()
{
const
materialId
=
this
.
form
.
materialId
?.
trim
()
||
''
const
materialId
=
this
.
form
.
materialId
?.
trim
()
||
''
;
// 增加分号,避免解析错误
if
(
!
materialId
)
{
if
(
!
materialId
)
{
this
.
inventoryList
=
[]
this
.
inventoryList
=
[];
this
.
closeLoading
()
this
.
closeLoading
();
return
return
;
}
}
try
{
try
{
this
.
loadingInstance
=
this
.
$loading
({
this
.
loadingInstance
=
this
.
$loading
({
text
:
'查询中...'
,
text
:
'查询中...'
,
target
:
this
.
$el
,
target
:
this
.
$el
,
lock
:
true
,
lock
:
true
,
background
:
'rgba(0, 0, 0, 0.7)'
background
:
'rgba(0, 0, 0, 0.7)'
})
});
const
res
=
await
listInventoryByMaterialId
(
materialId
)
const
res
=
await
listInventoryByMaterialId
(
materialId
);
// 增加分号
if
(
res
.
code
===
200
)
{
if
(
res
.
code
===
200
)
{
// 为每个库存行初始化扩展字段
// 按库存ID去重(修复语法:确保Map操作正确)
this
.
inventoryList
=
(
res
.
rows
||
[]).
map
(
item
=>
({
const
uniqueInventoryMap
=
new
Map
();
...
item
,
(
res
.
rows
||
[]).
forEach
(
item
=>
{
selectedQty
:
null
,
if
(
!
uniqueInventoryMap
.
has
(
item
.
id
))
{
plannedPackages
:
null
,
uniqueInventoryMap
.
set
(
item
.
id
,
item
);
divisor
:
null
,
// 约数
labelColor
:
''
,
// 标签颜色
unitPrice
:
null
,
// 单价
receivedAt
:
''
,
// 收货时间
receivedBy
:
''
,
// 收货人
voucherNumber
:
''
,
// 凭证号
remark
:
''
,
// 备注
quantity
:
item
.
quantity
||
0
,
lockedQuantity
:
item
.
lockedQuantity
||
0
}))
if
(
this
.
inventoryList
.
length
===
0
)
{
this
.
$message
.
warning
(
'未查询到该物料的库存信息'
)
}
}
else
{
this
.
inventoryList
=
[]
this
.
$message
.
error
(
res
.
msg
||
'查询库存失败'
)
}
}
}
catch
(
error
)
{
});
this
.
$message
.
error
(
'查询库存失败:'
+
(
error
.
message
||
'网络异常'
))
const
uniqueRows
=
Array
.
from
(
uniqueInventoryMap
.
values
());
// 增加分号
this
.
inventoryList
=
[]
}
finally
{
this
.
inventoryList
=
uniqueRows
.
map
(
item
=>
({
this
.
closeLoading
()
...
item
,
actualQuantity
:
null
,
plannedQuantity
:
null
,
divisor
:
null
,
labelColor
:
''
,
unitPrice
:
null
,
shippedAt
:
''
,
shippedBy
:
''
,
voucherNumber
:
''
,
remark
:
''
,
quantity
:
item
.
quantity
||
0
,
lockedQuantity
:
item
.
lockedQuantity
||
0
,
batchCode
:
item
.
batchId
||
''
}));
// 增加分号
if
(
this
.
inventoryList
.
length
===
0
)
{
this
.
$message
.
warning
(
'未查询到该物料的库存信息'
);
}
}
},
}
else
{
// 点击库存行触发 - 显示扩展字段填写区域
this
.
inventoryList
=
[];
this
.
$message
.
error
(
res
.
msg
||
'查询库存失败'
);
}
}
catch
(
error
)
{
this
.
$message
.
error
(
'查询库存失败:'
+
(
error
.
message
||
'网络异常'
));
this
.
inventoryList
=
[];
}
finally
{
this
.
closeLoading
();
}
},
handleRowClick
(
row
)
{
handleRowClick
(
row
)
{
if
(
!
row
)
return
this
.
currentSelectedRow
=
row
this
.
currentSelectedRow
=
row
// 自动选中当前行
this
.
$refs
.
inventoryTable
.
toggleRowSelection
(
row
,
true
)
},
},
handleRowQtyInput
(
row
)
{
handleRow
Actual
QtyInput
(
row
)
{
if
(
isNaN
(
row
.
selectedQty
)
||
row
.
selectedQ
ty
===
''
)
{
if
(
isNaN
(
row
.
actualQuantity
)
||
row
.
actualQuanti
ty
===
''
)
{
row
.
selectedQ
ty
=
null
row
.
actualQuanti
ty
=
null
return
return
}
}
const
availableQty
=
(
row
.
quantity
||
0
)
-
(
row
.
lockedQuantity
||
0
)
const
availableQty
=
(
row
.
quantity
||
0
)
-
(
row
.
lockedQuantity
||
0
)
if
(
row
.
selectedQ
ty
>
availableQty
)
{
if
(
row
.
actualQuanti
ty
>
availableQty
)
{
this
.
$message
.
warning
(
`
选择
数量不能超过可用数量
${
availableQty
}
`
)
this
.
$message
.
warning
(
`
实际
数量不能超过可用数量
${
availableQty
}
`
)
row
.
selectedQ
ty
=
availableQty
row
.
actualQuanti
ty
=
availableQty
}
else
if
(
row
.
selectedQ
ty
<
1
)
{
}
else
if
(
row
.
actualQuanti
ty
<
1
)
{
this
.
$message
.
warning
(
'
选择
数量不能小于1'
)
this
.
$message
.
warning
(
'
实际
数量不能小于1'
)
row
.
selectedQ
ty
=
1
row
.
actualQuanti
ty
=
1
}
}
// 核心改造1:清空其他行的实际数量,确保仅当前行有值
this
.
inventoryList
.
forEach
(
item
=>
{
if
(
item
.
id
!==
row
.
id
)
{
item
.
actualQuantity
=
null
item
.
plannedQuantity
=
null
item
.
divisor
=
null
item
.
labelColor
=
''
item
.
shippedBy
=
''
item
.
voucherNumber
=
''
item
.
remark
=
''
}
})
},
},
handleRowP
ackages
Input
(
row
)
{
handleRowP
lannedQty
Input
(
row
)
{
if
(
isNaN
(
row
.
planned
Packages
)
||
row
.
plannedPackages
===
''
)
{
if
(
isNaN
(
row
.
planned
Quantity
)
||
row
.
plannedQuantity
===
''
)
{
row
.
planned
Packages
=
null
row
.
planned
Quantity
=
null
return
return
}
}
if
(
row
.
plannedPackages
<
0
)
{
const
availableQty
=
(
row
.
quantity
||
0
)
-
(
row
.
lockedQuantity
||
0
)
this
.
$message
.
warning
(
'计划件数不能小于0'
)
if
(
row
.
plannedQuantity
>
availableQty
)
{
row
.
plannedPackages
=
0
this
.
$message
.
warning
(
`计划数量不能超过可用数量
${
availableQty
}
`
)
row
.
plannedQuantity
=
availableQty
}
else
if
(
row
.
plannedQuantity
<
1
)
{
this
.
$message
.
warning
(
'计划数量不能小于1'
)
row
.
plannedQuantity
=
1
}
}
},
},
handleSelectionChange
(
rows
)
{
syncDetails
()
{
// 过滤已取消选择的行
// 核心修复2:先清空明细,避免重复累加
this
.
details
=
this
.
details
.
filter
(
detail
=>
this
.
details
=
[]
rows
.
some
(
row
=>
row
.
id
===
detail
.
inventoryId
)
// 过滤出仅填写了实际数量的行(此时最多只有一行)
)
const
validRow
=
this
.
inventoryList
.
find
(
row
=>
{
// 处理选中行,携带行级扩展字段
if
(
row
.
actualQuantity
===
null
||
row
.
actualQuantity
===
''
||
isNaN
(
row
.
actualQuantity
))
return
false
rows
.
forEach
(
row
=>
{
// 选择数量为空则跳过
if
(
row
.
selectedQty
===
null
||
row
.
selectedQty
===
''
)
return
const
availableQty
=
(
row
.
quantity
||
0
)
-
(
row
.
lockedQuantity
||
0
)
const
availableQty
=
(
row
.
quantity
||
0
)
-
(
row
.
lockedQuantity
||
0
)
if
(
row
.
selectedQty
>
availableQty
||
row
.
selectedQty
<
1
)
{
return
row
.
actualQuantity
<=
availableQty
&&
row
.
actualQuantity
>=
1
this
.
$message
.
warning
(
`行
${
row
.
id
}
的选择数量不合法,请重新输入`
)
})
row
.
selectedQty
=
Math
.
min
(
Math
.
max
(
row
.
selectedQty
,
1
),
availableQty
)
}
// 校验行级必填字段(可根据实际需求调整)
if
(
!
row
.
divisor
&&
row
.
divisor
!==
0
)
{
this
.
$message
.
warning
(
`库存ID:
${
row
.
id
}
请填写约数`
)
return
}
if
(
!
row
.
labelColor
)
{
this
.
$message
.
warning
(
`库存ID:
${
row
.
id
}
请选择标签颜色`
)
return
}
if
(
!
row
.
unitPrice
&&
row
.
unitPrice
!==
0
)
{
this
.
$message
.
warning
(
`库存ID:
${
row
.
id
}
请填写单价`
)
return
}
if
(
!
row
.
receivedAt
)
{
this
.
$message
.
warning
(
`库存ID:
${
row
.
id
}
请选择收货时间`
)
return
}
if
(
!
row
.
receivedBy
)
{
this
.
$message
.
warning
(
`库存ID:
${
row
.
id
}
请填写收货人`
)
return
}
const
existingIndex
=
this
.
details
.
findIndex
(
d
=>
d
.
inventoryId
===
row
.
id
)
if
(
validRow
)
{
const
newDetail
=
{
const
newDetail
=
{
inventoryId
:
row
.
id
,
inventoryId
:
validRow
.
id
,
// 确保库存ID唯一
materialId
:
this
.
form
.
materialId
,
materialId
:
this
.
form
.
materialId
,
batch
Id
:
row
.
batchId
||
''
,
batch
Code
:
validRow
.
batchCode
||
''
,
warehouseId
:
r
ow
.
warehouseId
||
''
,
warehouseId
:
validR
ow
.
warehouseId
||
''
,
locationId
:
r
ow
.
locationId
||
''
,
locationId
:
validR
ow
.
locationId
||
''
,
plannedQuantity
:
row
.
selectedQty
,
plannedQuantity
:
Number
(
validRow
.
plannedQuantity
)
,
actualQuantity
:
row
.
selectedQty
,
actualQuantity
:
Number
(
validRow
.
actualQuantity
)
,
plannedPackages
:
row
.
plannedPackages
||
0
,
divisor
:
Number
(
validRow
.
divisor
)
||
0
,
actualPackages
:
row
.
plannedPackages
||
0
,
// 实际件数默认等于计划件数
labelColor
:
Number
(
validRow
.
labelColor
)
||
0
,
divisor
:
row
.
divisor
,
// 行级约数
unitPrice
:
Number
(
validRow
.
unitPrice
)
||
0
,
labelColor
:
row
.
labelColor
,
// 行级标签颜色
voucherNumber
:
validRow
.
voucherNumber
||
''
,
unitPrice
:
row
.
unitPrice
,
// 行级单价
itemStatus
:
Number
(
this
.
form
.
itemStatus
)
||
1
,
itemStatus
:
this
.
form
.
itemStatus
||
'1'
,
shippedAt
:
validRow
.
shippedAt
,
receivedAt
:
row
.
receivedAt
,
// 行级收货时间
shippedBy
:
validRow
.
shippedBy
,
re
ceivedBy
:
row
.
receivedBy
,
// 行级收货人
re
mark
:
validRow
.
remark
||
''
,
voucherNumber
:
row
.
voucherNumber
||
''
,
// 行级凭证号
isUsed
:
1
,
remark
:
row
.
remark
||
''
// 行级备注
sortNo
:
0
}
}
if
(
existingIndex
>
-
1
)
{
this
.
details
.
push
(
newDetail
)
this
.
details
.
splice
(
existingIndex
,
1
,
newDetail
)
}
}
else
{
this
.
details
.
push
(
newDetail
)
}
})
},
},
removeDetail
(
row
)
{
removeDetail
(
row
)
{
this
.
details
=
this
.
details
.
filter
(
d
=>
d
.
inventoryId
!==
row
.
inventoryId
)
this
.
details
=
this
.
details
.
filter
(
d
=>
d
.
inventoryId
!==
row
.
inventoryId
)
if
(
this
.
$refs
.
inventoryTable
&&
row
.
id
)
{
const
inventoryRow
=
this
.
inventoryList
.
find
(
item
=>
item
.
id
===
row
.
inventoryId
)
const
inventoryRow
=
this
.
inventoryList
.
find
(
item
=>
item
.
id
===
row
.
inventoryId
)
if
(
inventoryRow
)
{
if
(
inventoryRow
)
{
inventoryRow
.
actualQuantity
=
null
this
.
$refs
.
inventoryTable
.
toggleRowSelection
(
inventoryRow
,
false
)
inventoryRow
.
plannedQuantity
=
null
// 清空该行的填写内容
inventoryRow
.
divisor
=
null
inventoryRow
.
selectedQty
=
null
inventoryRow
.
labelColor
=
''
inventoryRow
.
plannedPackages
=
null
inventoryRow
.
unitPrice
=
null
inventoryRow
.
divisor
=
null
inventoryRow
.
shippedAt
=
''
inventoryRow
.
labelColor
=
''
inventoryRow
.
shippedBy
=
''
inventoryRow
.
unitPrice
=
null
inventoryRow
.
voucherNumber
=
''
inventoryRow
.
receivedAt
=
''
inventoryRow
.
remark
=
''
inventoryRow
.
receivedBy
=
''
if
(
this
.
currentSelectedRow
&&
this
.
currentSelectedRow
.
id
===
row
.
inventoryId
)
{
inventoryRow
.
voucherNumber
=
''
this
.
currentSelectedRow
=
null
inventoryRow
.
remark
=
''
// 如果删除的是当前选中行,重置currentSelectedRow
if
(
this
.
currentSelectedRow
&&
this
.
currentSelectedRow
.
id
===
row
.
inventoryId
)
{
this
.
currentSelectedRow
=
null
}
}
}
}
}
},
},
...
@@ -578,12 +528,53 @@ export default {
...
@@ -578,12 +528,53 @@ export default {
this
.
$message
.
error
(
'表单校验失败,请检查必填项'
)
this
.
$message
.
error
(
'表单校验失败,请检查必填项'
)
return
return
}
}
this
.
syncDetails
()
if
(
this
.
details
.
length
===
0
)
{
if
(
this
.
details
.
length
===
0
)
{
this
.
$message
.
error
(
'请选择库存并填写数量生成明细'
)
this
.
$message
.
error
(
'请填写实际数量并完善明细信息'
)
return
}
// 核心改造3:兜底校验 - 检查是否存在重复的inventoryId(防御性编程)
const
inventoryIds
=
this
.
details
.
map
(
d
=>
d
.
inventoryId
)
const
uniqueInventoryIds
=
[...
new
Set
(
inventoryIds
)]
if
(
uniqueInventoryIds
.
length
!==
inventoryIds
.
length
)
{
this
.
$message
.
error
(
'发现重复的库存ID明细,请重新选择!'
)
return
return
}
}
// 计算实际总数量
let
hasError
=
false
this
.
details
.
forEach
(
detail
=>
{
const
row
=
this
.
inventoryList
.
find
(
r
=>
r
.
id
===
detail
.
inventoryId
)
if
(
!
row
)
return
if
(
row
.
divisor
===
null
&&
row
.
divisor
!==
0
)
{
this
.
$message
.
warning
(
`库存ID:
${
row
.
id
}
请填写约数`
)
hasError
=
true
}
if
(
!
row
.
labelColor
)
{
this
.
$message
.
warning
(
`库存ID:
${
row
.
id
}
请选择标签颜色`
)
hasError
=
true
}
if
(
!
row
.
voucherNumber
)
{
this
.
$message
.
warning
(
`库存ID:
${
row
.
id
}
请填写凭证号`
)
hasError
=
true
}
if
(
!
row
.
shippedBy
)
{
this
.
$message
.
warning
(
`库存ID:
${
row
.
id
}
请填写发货方`
)
hasError
=
true
}
if
(
!
row
.
plannedQuantity
)
{
this
.
$message
.
warning
(
`库存ID:
${
row
.
id
}
请填写计划数量`
)
hasError
=
true
}
if
(
!
row
.
actualQuantity
)
{
this
.
$message
.
warning
(
`库存ID:
${
row
.
id
}
请填写实际数量`
)
hasError
=
true
}
})
if
(
hasError
)
return
const
totalActual
=
this
.
details
.
reduce
((
sum
,
d
)
=>
sum
+
(
d
.
actualQuantity
||
0
),
0
)
const
totalActual
=
this
.
details
.
reduce
((
sum
,
d
)
=>
sum
+
(
d
.
actualQuantity
||
0
),
0
)
if
(
this
.
form
.
totalPlannedQuantity
&&
this
.
form
.
totalPlannedQuantity
!==
totalActual
)
{
if
(
this
.
form
.
totalPlannedQuantity
&&
this
.
form
.
totalPlannedQuantity
!==
totalActual
)
{
try
{
try
{
...
@@ -613,7 +604,7 @@ export default {
...
@@ -613,7 +604,7 @@ export default {
this
.
selectedMaterialId
=
''
this
.
selectedMaterialId
=
''
this
.
selectedMaterialInfo
=
null
this
.
selectedMaterialInfo
=
null
this
.
openMaterialSelector
=
false
this
.
openMaterialSelector
=
false
this
.
currentSelectedRow
=
null
// 重置选中行
this
.
currentSelectedRow
=
null
if
(
this
.
$refs
.
detailForm
)
{
if
(
this
.
$refs
.
detailForm
)
{
this
.
$refs
.
detailForm
.
resetFields
()
this
.
$refs
.
detailForm
.
resetFields
()
}
}
...
@@ -683,7 +674,6 @@ export default {
...
@@ -683,7 +674,6 @@ export default {
min-height
:
500px
;
min-height
:
500px
;
}
}
/* 修复模态框遮罩层点击穿透问题 */
/
deep
/
.el-dialog__wrapper
{
/
deep
/
.el-dialog__wrapper
{
.el-modal__mask
{
.el-modal__mask
{
pointer-events
:
auto
!important
;
pointer-events
:
auto
!important
;
...
...
ruoyi-admin-vue/src/views/inventory/orders/index.vue
View file @
15102e6e
...
@@ -122,13 +122,20 @@
...
@@ -122,13 +122,20 @@
</el-row>
</el-row>
<!-- 主表格 -->
<!-- 主表格 -->
<el-table
v-loading=
"loading"
:data=
"ordersList"
@
selection-change=
"handleSelectionChange"
>
<el-table
ref=
"mainTable"
v-loading=
"loading"
:data=
"ordersList"
@
selection-change=
"handleSelectionChange"
:key=
"tableKey"
>
<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=
"orderId"
width=
"150"
/>
<el-table-column
label=
"出库单号"
align=
"center"
prop=
"orderId"
width=
"150"
/>
<el-table-column
label=
"系统编号"
align=
"center"
prop=
"systemNo"
width=
"150"
/>
<el-table-column
label=
"系统编号"
align=
"center"
prop=
"systemNo"
width=
"150"
/>
<el-table-column
label=
"入库类型"
align=
"center"
prop=
"orderTypeId"
width=
"120"
>
<el-table-column
label=
"入库类型"
align=
"center"
prop=
"orderTypeId"
width=
"120"
>
<template
slot-scope=
"scope"
>
<template
slot-scope=
"scope"
>
<dict-tag
:options=
"dict.type.inbound_order_type"
:value=
"scope.row.orderTypeId"
/>
<dict-tag
v-if=
"dict.type.inbound_order_type"
:options=
"dict.type.inbound_order_type"
:value=
"scope.row.orderTypeId"
/>
<span
v-else
>
-
</span>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"批次ID"
align=
"center"
prop=
"batchCode"
width=
"120"
/>
<el-table-column
label=
"批次ID"
align=
"center"
prop=
"batchCode"
width=
"120"
/>
...
@@ -136,7 +143,8 @@
...
@@ -136,7 +143,8 @@
<el-table-column
label=
"货主ID"
align=
"center"
prop=
"ownerId"
width=
"100"
/>
<el-table-column
label=
"货主ID"
align=
"center"
prop=
"ownerId"
width=
"100"
/>
<el-table-column
label=
"订单状态"
align=
"center"
prop=
"orderStatus"
width=
"150"
>
<el-table-column
label=
"订单状态"
align=
"center"
prop=
"orderStatus"
width=
"150"
>
<
template
slot-scope=
"scope"
>
<
template
slot-scope=
"scope"
>
<dict-tag
:options=
"dict.type.inbound_order_status"
:value=
"scope.row.orderStatus"
/>
<dict-tag
v-if=
"dict.type.inbound_order_status"
:options=
"dict.type.inbound_order_status"
:value=
"scope.row.orderStatus"
/>
<span
v-else
>
-
</span>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"出库日期"
align=
"center"
prop=
"inboundDate"
width=
"150"
>
<el-table-column
label=
"出库日期"
align=
"center"
prop=
"inboundDate"
width=
"150"
>
...
@@ -149,7 +157,7 @@
...
@@ -149,7 +157,7 @@
<
el
-
table
-
column
label
=
"实际量"
align
=
"center"
prop
=
"totalActualQuantity"
width
=
"100"
/>
<
el
-
table
-
column
label
=
"实际量"
align
=
"center"
prop
=
"totalActualQuantity"
width
=
"100"
/>
<
el
-
table
-
column
label
=
"总件数"
align
=
"center"
prop
=
"totalPackages"
width
=
"100"
/>
<
el
-
table
-
column
label
=
"总件数"
align
=
"center"
prop
=
"totalPackages"
width
=
"100"
/>
<
el
-
table
-
column
label
=
"备注"
align
=
"center"
prop
=
"remark"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"备注"
align
=
"center"
prop
=
"remark"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"操作"
align
=
"center"
class
-
name
=
"small-padding fixed-width"
width
=
"1
2
0"
>
<
el
-
table
-
column
label
=
"操作"
align
=
"center"
class
-
name
=
"small-padding fixed-width"
width
=
"1
8
0"
>
<
template
slot
-
scope
=
"scope"
>
<
template
slot
-
scope
=
"scope"
>
<
el
-
button
<
el
-
button
size
=
"mini"
size
=
"mini"
...
@@ -161,6 +169,13 @@
...
@@ -161,6 +169,13 @@
<
el
-
button
<
el
-
button
size
=
"mini"
size
=
"mini"
type
=
"text"
type
=
"text"
icon
=
"el-icon-send"
@
click
=
"handleShip(scope.row)"
v
-
hasPermi
=
"['inventory:orders:edit']"
>
出货
<
/el-button
>
<
el
-
button
size
=
"mini"
type
=
"text"
icon
=
"el-icon-delete"
icon
=
"el-icon-delete"
@
click
=
"handleDelete(scope.row)"
@
click
=
"handleDelete(scope.row)"
v
-
hasPermi
=
"['inventory:orders:remove']"
v
-
hasPermi
=
"['inventory:orders:remove']"
...
@@ -266,7 +281,6 @@
...
@@ -266,7 +281,6 @@
<
el
-
divider
content
-
position
=
"center"
>
入库单明细信息
<
/el-divider
>
<
el
-
divider
content
-
position
=
"center"
>
入库单明细信息
<
/el-divider
>
<
el
-
row
:
gutter
=
"10"
class
=
"mb8"
>
<
el
-
row
:
gutter
=
"10"
class
=
"mb8"
>
<
el
-
col
:
span
=
"1.5"
>
<
el
-
col
:
span
=
"1.5"
>
<!--
点击该按钮打开子组件弹窗
-->
<
el
-
button
type
=
"primary"
icon
=
"el-icon-plus"
size
=
"mini"
@
click
=
"openDetailDialog"
>
添加
<
/el-button
>
<
el
-
button
type
=
"primary"
icon
=
"el-icon-plus"
size
=
"mini"
@
click
=
"openDetailDialog"
>
添加
<
/el-button
>
<
/el-col
>
<
/el-col
>
<
el
-
col
:
span
=
"1.5"
>
<
el
-
col
:
span
=
"1.5"
>
...
@@ -274,37 +288,45 @@
...
@@ -274,37 +288,45 @@
<
/el-col
>
<
/el-col
>
<
/el-row
>
<
/el-row
>
<
el
-
table
<
el
-
table
:
data
=
"
in
boundOrderItemsList"
:
data
=
"
out
boundOrderItemsList"
:
row
-
class
-
name
=
"rowInboundOrderItemsIndex"
:
row
-
class
-
name
=
"rowInboundOrderItemsIndex"
@
selection
-
change
=
"handleInboundOrderItemsSelectionChange"
@
selection
-
change
=
"handleInboundOrderItemsSelectionChange"
ref
=
"inboundOrderItems"
ref
=
"inboundOrderItems"
border
border
style
=
"width: 100%;"
style
=
"width: 100%;"
v
-
if
=
"outboundOrderItemsList.length > 0"
:
row
-
key
=
"item => item.inventoryId"
>
>
<
el
-
table
-
column
type
=
"selection"
width
=
"50"
align
=
"center"
/>
<
el
-
table
-
column
type
=
"selection"
width
=
"50"
align
=
"center"
/>
<
el
-
table
-
column
label
=
"序号"
align
=
"center"
prop
=
"index"
width
=
"50"
/>
<
el
-
table
-
column
label
=
"序号"
align
=
"center"
prop
=
"index"
width
=
"50"
/>
<
el
-
table
-
column
prop
=
"inventoryId"
label
=
"库存ID"
width
=
"100"
/>
<
el
-
table
-
column
label
=
"货物ID"
prop
=
"materialId"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"货物ID"
prop
=
"materialId"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"批次ID"
prop
=
"batch
Id
"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"批次ID"
prop
=
"batch
Code
"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"仓库ID"
prop
=
"warehouseId"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"仓库ID"
prop
=
"warehouseId"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"库位ID"
prop
=
"locationId"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"库位ID"
prop
=
"locationId"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"计划数量"
prop
=
"plannedQuantity"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"计划数量"
prop
=
"plannedQuantity"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"实际数量"
prop
=
"actualQuantity"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"实际数量"
prop
=
"actualQuantity"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"计划件数"
prop
=
"plannedPackages"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"实际件数"
prop
=
"actualPackages"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"约数"
prop
=
"divisor"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"约数"
prop
=
"divisor"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"标签颜色"
prop
=
"labelColor"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"标签颜色"
prop
=
"labelColor"
width
=
"150"
>
<
template
slot
-
scope
=
"scope"
>
{{
getLabelColorText
(
scope
.
row
.
labelColor
)
}}
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"单价"
prop
=
"unitPrice"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"单价"
prop
=
"unitPrice"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"凭证号"
prop
=
"voucherNumber"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"状态"
prop
=
"itemStatus"
width
=
"150"
>
<
el
-
table
-
column
label
=
"状态"
prop
=
"itemStatus"
width
=
"150"
>
<
template
slot
-
scope
=
"scope"
>
<
template
slot
-
scope
=
"scope"
>
<
dict
-
tag
:
options
=
"dict.type.inbound_order_item_status"
:
value
=
"scope.row.itemStatus"
/>
<
dict
-
tag
v
-
if
=
"dict.type.inbound_order_item_status"
:
options
=
"dict.type.inbound_order_item_status"
:
value
=
"scope.row.itemStatus"
/>
<
span
v
-
else
>-<
/span
>
<
/template
>
<
/template
>
<
/el-table-column
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"
收货时间"
prop
=
"receiv
edAt"
width
=
"150"
>
<
el
-
table
-
column
label
=
"
发货时间"
prop
=
"shipp
edAt"
width
=
"150"
>
<
template
slot
-
scope
=
"scope"
>
<
template
slot
-
scope
=
"scope"
>
<
span
>
{{
parseTime
(
scope
.
row
.
receiv
edAt
,
'{y
}
-{m
}
-{d
}
{h
}
:{i
}
:{s
}
'
)
}}
<
/span
>
<
span
>
{{
parseTime
(
scope
.
row
.
shipp
edAt
,
'{y
}
-{m
}
-{d
}
{h
}
:{i
}
:{s
}
'
)
}}
<
/span
>
<
/template
>
<
/template
>
<
/el-table-column
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"收货人"
prop
=
"receivedBy"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"发货方"
prop
=
"shippedBy"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"备注"
prop
=
"remark"
width
=
"150"
/>
<
el
-
table
-
column
label
=
"操作"
align
=
"center"
width
=
"80"
>
<
el
-
table
-
column
label
=
"操作"
align
=
"center"
width
=
"80"
>
<
template
slot
-
scope
=
"scope"
>
<
template
slot
-
scope
=
"scope"
>
<
el
-
button
<
el
-
button
...
@@ -316,6 +338,9 @@
...
@@ -316,6 +338,9 @@
<
/template
>
<
/template
>
<
/el-table-column
>
<
/el-table-column
>
<
/el-table
>
<
/el-table
>
<
div
v
-
else
class
=
"empty-tip"
style
=
"text-align: center; padding: 20px; color: #999;"
>
暂无明细数据,请点击添加按钮添加
<
/div
>
<
/el-form
>
<
/el-form
>
<
div
slot
=
"footer"
class
=
"dialog-footer"
>
<
div
slot
=
"footer"
class
=
"dialog-footer"
>
<
el
-
button
type
=
"primary"
@
click
=
"submitForm"
>
确
定
<
/el-button
>
<
el
-
button
type
=
"primary"
@
click
=
"submitForm"
>
确
定
<
/el-button
>
...
@@ -323,7 +348,7 @@
...
@@ -323,7 +348,7 @@
<
/div
>
<
/div
>
<
/el-dialog
>
<
/el-dialog
>
<!--
明细项添加
/
编辑子组件弹窗
(
OutboundOrderFormWithItems
)
-->
<!--
明细项添加
/
编辑子组件弹窗
-->
<
OutboundOrderFormWithItems
<
OutboundOrderFormWithItems
:
title
=
"detailDialogTitle"
:
title
=
"detailDialogTitle"
:
open
=
"detailDialogOpen"
:
open
=
"detailDialogOpen"
...
@@ -336,18 +361,19 @@
...
@@ -336,18 +361,19 @@
<
/template
>
<
/template
>
<
script
>
<
script
>
import
{
listOrders
,
getOrders
,
delOrders
,
addOrders
,
updateOrders
}
from
"@/api/inventory/orders"
import
{
listOrders
,
getOrders
,
delOrders
,
addOrders
,
updateOrders
,
ship
}
from
"@/api/inventory/orders"
// 导入明细子组件
import
OutboundOrderFormWithItems
from
'./OutboundOrderFormWithItems.vue'
import
OutboundOrderFormWithItems
from
'./OutboundOrderFormWithItems.vue'
export
default
{
export
default
{
name
:
"Orders"
,
name
:
"Orders"
,
dicts
:
[
'inbound_order_status'
,
'inbound_order_type'
,
'inbound_order_item_status'
],
dicts
:
[
'inbound_order_status'
,
'inbound_order_type'
,
'inbound_order_item_status'
],
components
:
{
components
:
{
OutboundOrderFormWithItems
// 注册子组件
OutboundOrderFormWithItems
}
,
}
,
data
()
{
data
()
{
return
{
return
{
// 添加tableKey解决tableId渲染问题
tableKey
:
1
,
// 遮罩层
// 遮罩层
loading
:
true
,
loading
:
true
,
// 选中数组
// 选中数组
...
@@ -366,31 +392,34 @@ export default {
...
@@ -366,31 +392,34 @@ export default {
title
:
""
,
title
:
""
,
// 主弹窗是否显示
// 主弹窗是否显示
open
:
false
,
open
:
false
,
// 明细
表格数据
// 明细
列表
in
boundOrderItemsList
:
[],
out
boundOrderItemsList
:
[],
// 选中的明细行
// 选中的明细行
selectedInboundOrderItems
:
[],
selectedInboundOrderItems
:
[],
// 明细子弹窗相关
// 明细子弹窗相关
detailDialogOpen
:
false
,
// 子弹窗是否显示
detailDialogOpen
:
false
,
detailDialogTitle
:
"新增明细项"
,
// 子弹窗标题
detailDialogTitle
:
"新增明细项"
,
currentDetailItem
:
{
currentDetailItem
:
{
materialUuids
:
''
,
// 存储物料选择器返回的materialCodes
inventoryId
:
''
,
materialUuids
:
''
,
materialId
:
''
,
materialId
:
''
,
batch
Id
:
''
,
batch
Code
:
''
,
warehouseId
:
''
,
warehouseId
:
''
,
locationId
:
''
,
locationId
:
''
,
plannedQuantity
:
''
,
plannedQuantity
:
''
,
actualQuantity
:
''
,
actualQuantity
:
''
,
plannedPackages
:
''
,
actualPackages
:
''
,
divisor
:
''
,
divisor
:
''
,
labelColor
:
''
,
labelColor
:
''
,
unitPrice
:
''
,
unitPrice
:
''
,
itemStatus
:
'pending'
,
voucherNumber
:
''
,
receivedAt
:
''
,
itemStatus
:
1
,
receivedBy
:
''
shippedAt
:
''
,
}
,
// 当前编辑的明细项
shippedBy
:
''
,
isEditDetail
:
false
,
// 标记是否为编辑明细
isUsed
:
1
,
sortNo
:
0
,
remark
:
''
}
,
isEditDetail
:
false
,
// 查询参数
// 查询参数
queryParams
:
{
queryParams
:
{
pageNum
:
1
,
pageNum
:
1
,
...
@@ -423,30 +452,59 @@ export default {
...
@@ -423,30 +452,59 @@ export default {
}
}
}
,
}
,
created
()
{
created
()
{
this
.
getList
()
// 延迟加载避免初始化渲染问题
this
.
$nextTick
(()
=>
{
this
.
getList
()
}
)
}
,
}
,
methods
:
{
methods
:
{
// ========== 明细子弹窗相关方法 ==========
// 核心出货方法
async
handleShip
(
row
)
{
try
{
// 调用ship接口提交数据到后端
await
ship
(
row
)
// 提示成功并刷新列表
this
.
$modal
.
msgSuccess
(
"出货操作成功,数据已提交到后端"
)
this
.
getList
()
}
catch
(
error
)
{
// 错误处理
this
.
$modal
.
msgError
(
error
.
msg
||
"出货操作失败"
)
}
}
,
// 标签颜色值转文本
getLabelColorText
(
value
)
{
const
colorMap
=
{
'1'
:
'红色'
,
'2'
:
'蓝色'
,
'3'
:
'绿色'
,
'4'
:
'黄色'
}
return
colorMap
[
value
]
||
'-'
}
,
// 打开明细子弹窗(新增)
// 打开明细子弹窗(新增)
openDetailDialog
()
{
openDetailDialog
()
{
this
.
isEditDetail
=
false
this
.
isEditDetail
=
false
this
.
detailDialogTitle
=
"新增明细项"
this
.
detailDialogTitle
=
"新增明细项"
this
.
currentDetailItem
=
{
this
.
currentDetailItem
=
{
materialUuids
:
''
,
// 初始化materialUuids(接收materialCodes)
inventoryId
:
''
,
materialUuids
:
''
,
materialId
:
''
,
materialId
:
''
,
batch
Id
:
''
,
batch
Code
:
''
,
warehouseId
:
''
,
warehouseId
:
this
.
form
.
warehouseId
||
''
,
locationId
:
''
,
locationId
:
''
,
plannedQuantity
:
''
,
plannedQuantity
:
''
,
actualQuantity
:
''
,
actualQuantity
:
''
,
plannedPackages
:
''
,
actualPackages
:
''
,
divisor
:
''
,
divisor
:
''
,
labelColor
:
''
,
labelColor
:
''
,
unitPrice
:
''
,
unitPrice
:
''
,
itemStatus
:
'pending'
,
// 默认状态
voucherNumber
:
''
,
receivedAt
:
''
,
itemStatus
:
1
,
receivedBy
:
''
shippedAt
:
''
,
shippedBy
:
''
,
isUsed
:
1
,
sortNo
:
0
,
remark
:
''
}
}
this
.
detailDialogOpen
=
true
this
.
detailDialogOpen
=
true
}
,
}
,
...
@@ -454,73 +512,108 @@ export default {
...
@@ -454,73 +512,108 @@ export default {
editDetailItem
(
row
)
{
editDetailItem
(
row
)
{
this
.
isEditDetail
=
true
this
.
isEditDetail
=
true
this
.
detailDialogTitle
=
"编辑明细项"
this
.
detailDialogTitle
=
"编辑明细项"
// 兼容materialUuids:优先取row.materialUuids,无则用materialId(适配返回的materialCodes)
this
.
currentDetailItem
=
{
this
.
currentDetailItem
=
{
...
row
,
...
row
,
materialUuids
:
row
.
materialUuids
||
row
.
materialId
||
''
inventoryId
:
row
.
inventoryId
||
''
,
}
materialUuids
:
row
.
materialId
||
''
,
divisor
:
row
.
divisor
||
0
,
itemStatus
:
row
.
itemStatus
||
1
,
labelColor
:
row
.
labelColor
||
0
,
plannedQuantity
:
row
.
plannedQuantity
||
0
,
actualQuantity
:
row
.
actualQuantity
||
0
,
remark
:
row
.
remark
||
''
}
this
.
detailDialogOpen
=
true
this
.
detailDialogOpen
=
true
}
,
}
,
// 接收子组件提交的明细数据(核心修
改:适配materialCodes返回格式
)
// 接收子组件提交的明细数据(核心修
复:新增去重逻辑
)
handleDetailSubmit
(
details
)
{
handleDetailSubmit
(
details
)
{
// 兼容子组件返回格式:如果是materialCodes结构,提取第一个值赋值给materialId
const
formatDetail
=
(
item
)
=>
{
// 处理物料选择器返回的materialCodes数组
if
(
item
.
materialUuids
&&
Array
.
isArray
(
item
.
materialUuids
))
{
item
.
materialId
=
item
.
materialUuids
[
0
]
||
''
// 单选取第一个值
item
.
materialUuids
=
item
.
materialUuids
[
0
]
||
''
// 同步更新materialUuids
}
// 兼容子组件返回的原始格式
return
item
}
// 统一转为数组处理
const
detailList
=
Array
.
isArray
(
details
)
?
details
:
[
details
]
const
detailList
=
Array
.
isArray
(
details
)
?
details
:
[
details
]
// 格式化每条明细的物料字段
const
formattedList
=
detailList
.
map
(
item
=>
formatDetail
(
item
))
if
(
this
.
isEditDetail
)
{
if
(
this
.
isEditDetail
)
{
// 编辑模式
:替换原有单条数据
// 编辑模式
const
editIndex
=
this
.
in
boundOrderItemsList
.
findIndex
(
item
=>
item
.
index
===
this
.
currentDetailItem
.
index
)
const
editIndex
=
this
.
out
boundOrderItemsList
.
findIndex
(
item
=>
item
.
index
===
this
.
currentDetailItem
.
index
)
if
(
editIndex
>
-
1
)
{
if
(
editIndex
>
-
1
)
{
this
.
inboundOrderItemsList
.
splice
(
editIndex
,
1
,
{
this
.
outboundOrderItemsList
.
splice
(
editIndex
,
1
,
{
...
formattedList
[
0
],
...
detailList
[
0
],
index
:
this
.
currentDetailItem
.
index
index
:
this
.
currentDetailItem
.
index
,
orderId
:
this
.
form
.
id
||
this
.
form
.
orderId
,
inventoryId
:
detailList
[
0
].
inventoryId
||
''
,
itemStatus
:
Number
(
detailList
[
0
].
itemStatus
)
||
1
,
labelColor
:
Number
(
detailList
[
0
].
labelColor
)
||
0
,
divisor
:
Number
(
detailList
[
0
].
divisor
)
||
0
,
plannedQuantity
:
Number
(
detailList
[
0
].
plannedQuantity
)
||
0
,
actualQuantity
:
Number
(
detailList
[
0
].
actualQuantity
)
||
0
,
isUsed
:
1
,
sortNo
:
0
,
remark
:
detailList
[
0
].
remark
||
''
}
)
}
)
}
}
this
.
$message
.
success
(
"编辑明细成功"
)
this
.
$message
.
success
(
"编辑明细成功"
)
}
else
{
}
else
{
// 新增模式:批量添加多条明细
// 新增模式:按库存ID去重,避免重复添加
const
newDetails
=
formattedList
.
map
((
item
,
idx
)
=>
{
const
existingInventoryIds
=
new
Set
(
this
.
outboundOrderItemsList
.
map
(
item
=>
item
.
inventoryId
))
const
newIndex
=
this
.
inboundOrderItemsList
.
length
+
idx
+
1
// 过滤已存在的库存ID
return
{
...
item
,
index
:
newIndex
}
const
newDetails
=
detailList
}
)
.
filter
(
item
=>
item
.
inventoryId
&&
!
existingInventoryIds
.
has
(
item
.
inventoryId
))
this
.
inboundOrderItemsList
=
[...
this
.
inboundOrderItemsList
,
...
newDetails
]
.
map
((
item
,
idx
)
=>
{
const
newIndex
=
this
.
outboundOrderItemsList
.
length
+
idx
+
1
return
{
...
item
,
index
:
newIndex
,
orderId
:
this
.
form
.
id
||
this
.
form
.
orderId
,
inventoryId
:
item
.
inventoryId
||
''
,
itemStatus
:
Number
(
item
.
itemStatus
)
||
1
,
labelColor
:
Number
(
item
.
labelColor
)
||
0
,
divisor
:
Number
(
item
.
divisor
)
||
0
,
plannedQuantity
:
Number
(
item
.
plannedQuantity
)
||
0
,
actualQuantity
:
Number
(
item
.
actualQuantity
)
||
0
,
isUsed
:
1
,
sortNo
:
0
,
remark
:
item
.
remark
||
''
}
}
)
// 自动计算主表总数量
// 无新数据则提示
if
(
newDetails
.
length
===
0
)
{
this
.
$message
.
warning
(
"该库存明细已存在,无法重复添加"
)
this
.
detailDialogOpen
=
false
return
}
this
.
outboundOrderItemsList
=
[...
this
.
outboundOrderItemsList
,
...
newDetails
]
this
.
calcTotalQuantity
()
this
.
calcTotalQuantity
()
this
.
$message
.
success
(
`成功新增${newDetails.length
}
条明细`
)
this
.
$message
.
success
(
`成功新增${newDetails.length
}
条明细`
)
}
}
this
.
detailDialogOpen
=
false
this
.
detailDialogOpen
=
false
// 更新tableKey触发重新渲染
this
.
tableKey
+=
1
}
,
}
,
// 计算主表总数量
// 自动计算主表的计划总量/实际总量/总件数
calcTotalQuantity
()
{
calcTotalQuantity
()
{
const
totalPlanned
=
this
.
inboundOrderItemsList
.
reduce
((
sum
,
item
)
=>
sum
+
(
Number
(
item
.
plannedQuantity
)
||
0
),
0
)
const
totalPlanned
=
this
.
outboundOrderItemsList
.
reduce
((
sum
,
item
)
=>
{
const
totalActual
=
this
.
inboundOrderItemsList
.
reduce
((
sum
,
item
)
=>
sum
+
(
Number
(
item
.
actualQuantity
)
||
0
),
0
)
const
qty
=
item
.
plannedQuantity
!==
null
?
Number
(
item
.
plannedQuantity
)
:
0
const
totalPackages
=
this
.
inboundOrderItemsList
.
reduce
((
sum
,
item
)
=>
sum
+
(
Number
(
item
.
actualPackages
)
||
0
),
0
)
return
sum
+
qty
}
,
0
)
const
totalActual
=
this
.
outboundOrderItemsList
.
reduce
((
sum
,
item
)
=>
{
const
qty
=
item
.
actualQuantity
!==
null
?
Number
(
item
.
actualQuantity
)
:
0
return
sum
+
qty
}
,
0
)
const
totalPackages
=
this
.
outboundOrderItemsList
.
reduce
((
sum
,
item
)
=>
{
const
divisor
=
item
.
divisor
!==
null
?
Number
(
item
.
divisor
)
:
1
const
actualQty
=
item
.
actualQuantity
!==
null
?
Number
(
item
.
actualQuantity
)
:
0
return
sum
+
Math
.
ceil
(
actualQty
/
divisor
)
}
,
0
)
this
.
form
.
totalPlannedQuantity
=
totalPlanned
this
.
form
.
totalPlannedQuantity
=
totalPlanned
this
.
form
.
totalActualQuantity
=
totalActual
this
.
form
.
totalActualQuantity
=
totalActual
this
.
form
.
totalPackages
=
totalPackages
this
.
form
.
totalPackages
=
totalPackages
}
,
}
,
// ========== 明细表格相关方法 ==========
// 生成明细表格行序号
// 生成明细表格行序号
rowInboundOrderItemsIndex
({
row
,
rowIndex
}
)
{
rowInboundOrderItemsIndex
({
row
,
rowIndex
}
)
{
if
(
!
row
.
index
)
row
.
index
=
rowIndex
+
1
if
(
row
.
index
===
undefined
||
row
.
index
===
null
)
{
row
.
index
=
rowIndex
+
1
}
}
,
}
,
// 明细表格选择事件
// 明细表格选择事件
handleInboundOrderItemsSelectionChange
(
val
)
{
handleInboundOrderItemsSelectionChange
(
val
)
{
...
@@ -532,30 +625,32 @@ export default {
...
@@ -532,30 +625,32 @@ export default {
this
.
$message
.
warning
(
'请选择要删除的明细行'
)
this
.
$message
.
warning
(
'请选择要删除的明细行'
)
return
return
}
}
// 获取选中行索引并倒序删除
const
selectedIndexes
=
this
.
selectedInboundOrderItems
.
map
(
item
=>
const
selectedIndexes
=
this
.
selectedInboundOrderItems
.
map
(
item
=>
this
.
in
boundOrderItemsList
.
findIndex
(
row
=>
row
.
index
===
item
.
index
)
this
.
out
boundOrderItemsList
.
findIndex
(
row
=>
row
.
index
===
item
.
index
)
)
)
selectedIndexes
.
sort
((
a
,
b
)
=>
b
-
a
).
forEach
(
index
=>
{
selectedIndexes
.
sort
((
a
,
b
)
=>
b
-
a
).
forEach
(
index
=>
{
this
.
in
boundOrderItemsList
.
splice
(
index
,
1
)
this
.
out
boundOrderItemsList
.
splice
(
index
,
1
)
}
)
}
)
// 重新
更新
序号
// 重新
排序
序号
this
.
in
boundOrderItemsList
.
forEach
((
row
,
index
)
=>
{
this
.
out
boundOrderItemsList
.
forEach
((
row
,
index
)
=>
{
row
.
index
=
index
+
1
row
.
index
=
index
+
1
}
)
}
)
// 重新计算总数量
this
.
calcTotalQuantity
()
this
.
calcTotalQuantity
()
this
.
$message
.
success
(
'明细行删除成功'
)
this
.
$message
.
success
(
'明细行删除成功'
)
}
,
}
,
// ========== 主表格/表单相关方法 ==========
/** 查询出库单主列表 */
/** 查询出库单主列表 */
getList
()
{
getList
()
{
this
.
loading
=
true
this
.
loading
=
true
listOrders
(
this
.
queryParams
).
then
(
response
=>
{
listOrders
(
this
.
queryParams
).
then
(
response
=>
{
this
.
ordersList
=
response
.
rows
this
.
ordersList
=
response
.
rows
||
[]
this
.
total
=
response
.
total
this
.
total
=
response
.
total
||
0
this
.
loading
=
false
// 更新tableKey解决渲染问题
this
.
tableKey
+=
1
}
).
catch
(()
=>
{
this
.
loading
=
false
this
.
loading
=
false
this
.
ordersList
=
[]
this
.
total
=
0
}
)
}
)
}
,
}
,
// 取消按钮
// 取消按钮
...
@@ -587,10 +682,12 @@ export default {
...
@@ -587,10 +682,12 @@ export default {
updateTime
:
null
,
updateTime
:
null
,
updateUserCode
:
null
updateUserCode
:
null
}
}
// 重置明细表格
this
.
outboundOrderItemsList
=
[]
this
.
inboundOrderItemsList
=
[]
this
.
selectedInboundOrderItems
=
[]
this
.
selectedInboundOrderItems
=
[]
this
.
resetForm
(
"form"
)
// 检查ref存在性
if
(
this
.
$refs
.
form
)
{
this
.
resetForm
(
"form"
)
}
}
,
}
,
/** 搜索按钮操作 */
/** 搜索按钮操作 */
handleQuery
()
{
handleQuery
()
{
...
@@ -599,7 +696,10 @@ export default {
...
@@ -599,7 +696,10 @@ export default {
}
,
}
,
/** 重置按钮操作 */
/** 重置按钮操作 */
resetQuery
()
{
resetQuery
()
{
this
.
resetForm
(
"queryForm"
)
// 检查ref存在性
if
(
this
.
$refs
.
queryForm
)
{
this
.
resetForm
(
"queryForm"
)
}
this
.
handleQuery
()
this
.
handleQuery
()
}
,
}
,
// 多选框选中数据
// 多选框选中数据
...
@@ -614,39 +714,95 @@ export default {
...
@@ -614,39 +714,95 @@ export default {
this
.
open
=
true
this
.
open
=
true
this
.
title
=
"添加出库单"
this
.
title
=
"添加出库单"
}
,
}
,
/** 修改按钮操作 */
/** 修改按钮操作
(修复:加载明细时去重)
*/
handleUpdate
(
row
)
{
handleUpdate
(
row
)
{
this
.
reset
()
this
.
reset
()
const
id
=
row
.
id
||
this
.
ids
const
id
=
row
.
id
||
this
.
ids
getOrders
(
id
).
then
(
response
=>
{
getOrders
(
id
).
then
(
response
=>
{
this
.
form
=
response
.
data
this
.
form
=
response
.
data
||
{
}
// 如果有明细数据,初始化明细表格
if
(
response
.
data
&&
response
.
data
.
outboundOrderItemsList
&&
Array
.
isArray
(
response
.
data
.
outboundOrderItemsList
))
{
if
(
response
.
data
.
items
)
{
// 按库存ID去重
this
.
inboundOrderItemsList
=
response
.
data
.
items
.
map
((
item
,
index
)
=>
({
const
uniqueItemsMap
=
new
Map
()
response
.
data
.
outboundOrderItemsList
.
forEach
(
item
=>
{
if
(
item
.
inventoryId
&&
!
uniqueItemsMap
.
has
(
item
.
inventoryId
))
{
uniqueItemsMap
.
set
(
item
.
inventoryId
,
item
)
}
}
)
const
uniqueItems
=
Array
.
from
(
uniqueItemsMap
.
values
())
this
.
outboundOrderItemsList
=
uniqueItems
.
map
((
item
,
index
)
=>
({
...
item
,
...
item
,
// 兼容materialUuids:适配物料选择器返回的materialCodes格式
index
:
index
+
1
,
materialUuids
:
item
.
materialUuids
||
item
.
materialId
||
''
,
inventoryId
:
item
.
inventoryId
||
''
,
index
:
index
+
1
divisor
:
item
.
divisor
!==
null
?
Number
(
item
.
divisor
)
:
0
,
itemStatus
:
item
.
itemStatus
!==
null
?
Number
(
item
.
itemStatus
)
:
1
,
labelColor
:
item
.
labelColor
!==
null
?
Number
(
item
.
labelColor
)
:
0
,
plannedQuantity
:
item
.
plannedQuantity
!==
null
?
Number
(
item
.
plannedQuantity
)
:
0
,
actualQuantity
:
item
.
actualQuantity
!==
null
?
Number
(
item
.
actualQuantity
)
:
0
,
isUsed
:
item
.
isUsed
!==
null
?
Number
(
item
.
isUsed
)
:
1
,
sortNo
:
item
.
sortNo
!==
null
?
Number
(
item
.
sortNo
)
:
0
,
materialUuids
:
item
.
materialId
||
''
,
warehouseId
:
item
.
warehouseId
||
''
,
locationId
:
item
.
locationId
||
''
,
voucherNumber
:
item
.
voucherNumber
||
''
,
shippedAt
:
item
.
shippedAt
||
''
,
shippedBy
:
item
.
shippedBy
||
''
,
remark
:
item
.
remark
||
''
,
orderId
:
response
.
data
.
id
}
))
}
))
// 计算总数量
this
.
calcTotalQuantity
()
this
.
calcTotalQuantity
()
}
}
this
.
open
=
true
this
.
open
=
true
this
.
title
=
"修改出库单"
this
.
title
=
"修改出库单"
}
)
}
)
}
,
}
,
/** 提交按钮 */
/** 提交按钮
(修复:提交前最后去重)
*/
submitForm
()
{
submitForm
()
{
// 检查表单ref存在性
if
(
!
this
.
$refs
.
form
)
{
this
.
$message
.
error
(
'表单初始化失败,请重试'
)
return
}
this
.
$refs
[
"form"
].
validate
(
async
(
valid
)
=>
{
this
.
$refs
[
"form"
].
validate
(
async
(
valid
)
=>
{
if
(
valid
)
{
if
(
valid
)
{
// 组装完整数据(主表+明细)
if
(
this
.
outboundOrderItemsList
.
length
===
0
)
{
this
.
$message
.
warning
(
'请至少添加一条明细数据'
)
return
}
// 提交前按库存ID去重
const
uniqueDetailsMap
=
new
Map
()
this
.
outboundOrderItemsList
.
forEach
(
item
=>
{
if
(
item
.
inventoryId
&&
!
uniqueDetailsMap
.
has
(
item
.
inventoryId
))
{
uniqueDetailsMap
.
set
(
item
.
inventoryId
,
item
)
}
}
)
const
uniqueDetails
=
Array
.
from
(
uniqueDetailsMap
.
values
())
const
submitData
=
{
const
submitData
=
{
...
this
.
form
,
...
this
.
form
,
items
:
this
.
inboundOrderItemsList
.
map
(
item
=>
{
outboundOrderItemsList
:
uniqueDetails
.
map
(
item
=>
{
const
{
index
,
...
rest
}
=
item
// 剔除序号
const
{
index
,
materialUuids
,
...
rest
}
=
item
// 提交时确保materialId是单选的物料编码(从materialUuids/原materialId取值)
return
{
rest
.
materialId
=
rest
.
materialUuids
||
rest
.
materialId
||
''
...
rest
,
return
rest
orderId
:
this
.
form
.
id
||
this
.
form
.
orderId
,
inventoryId
:
rest
.
inventoryId
||
''
,
materialId
:
rest
.
materialId
||
''
,
batchCode
:
rest
.
batchCode
||
''
,
warehouseId
:
rest
.
warehouseId
||
''
,
locationId
:
rest
.
locationId
||
''
,
plannedQuantity
:
Number
(
rest
.
plannedQuantity
)
||
0
,
actualQuantity
:
Number
(
rest
.
actualQuantity
)
||
0
,
divisor
:
Number
(
rest
.
divisor
)
||
0
,
labelColor
:
Number
(
rest
.
labelColor
)
||
0
,
voucherNumber
:
rest
.
voucherNumber
||
''
,
itemStatus
:
Number
(
rest
.
itemStatus
)
||
1
,
shippedAt
:
rest
.
shippedAt
||
''
,
shippedBy
:
rest
.
shippedBy
||
''
,
remark
:
rest
.
remark
||
''
,
isUsed
:
1
,
sortNo
:
Number
(
rest
.
sortNo
)
||
0
}
}
)
}
)
}
}
try
{
try
{
...
@@ -660,8 +816,13 @@ export default {
...
@@ -660,8 +816,13 @@ export default {
this
.
open
=
false
this
.
open
=
false
this
.
getList
()
this
.
getList
()
}
catch
(
error
)
{
}
catch
(
error
)
{
this
.
$modal
.
msgError
(
error
.
msg
||
"操作失败"
)
// 【关键】捕获异常时弹窗(覆盖接口报错场景)
}
if
(
error
!==
'cancel'
)
{
// 排除用户点击取消的情况
// 优先用后端返回的msg,没有则显示默认文案
const
errorMsg
=
error
?.
response
?.
data
?.
msg
||
'库存被修改请重新确认'
;
this
.
$modal
.
msgError
(
errorMsg
);
// 核心弹窗代码(若依风格错误弹窗)
}
}
}
}
}
)
}
)
}
,
}
,
...
@@ -703,4 +864,9 @@ export default {
...
@@ -703,4 +864,9 @@ export default {
.
el
-
table
{
.
el
-
table
{
--
el
-
table
-
row
-
hover
-
bg
-
color
:
#
f8f9fa
;
--
el
-
table
-
row
-
hover
-
bg
-
color
:
#
f8f9fa
;
}
}
/* 空数据提示样式 */
.
empty
-
tip
{
color
:
#
999
;
font
-
size
:
14
px
;
}
<
/style>
<
/style>
\ No newline at end of file
ruoyi-admin/src/main/java/com/ruoyi/web/controller/inventory/InboundOrderItemsController.java
View file @
15102e6e
...
@@ -4,7 +4,7 @@ import java.util.List;
...
@@ -4,7 +4,7 @@ import java.util.List;
import
java.util.UUID
;
import
java.util.UUID
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpServletResponse
;
import
com.ruoyi.
common.core.domain.entity.Material
s
;
import
com.ruoyi.
inventory.domain.InboundOrderItem
s
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.GetMapping
;
...
@@ -19,7 +19,6 @@ import com.ruoyi.common.annotation.Log;
...
@@ -19,7 +19,6 @@ import com.ruoyi.common.annotation.Log;
import
com.ruoyi.common.core.controller.BaseController
;
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.enums.BusinessType
;
import
com.ruoyi.common.enums.BusinessType
;
import
com.ruoyi.inventory.domain.InboundOrderItems
;
import
com.ruoyi.inventory.service.IInboundOrderItemsService
;
import
com.ruoyi.inventory.service.IInboundOrderItemsService
;
import
com.ruoyi.common.utils.poi.ExcelUtil
;
import
com.ruoyi.common.utils.poi.ExcelUtil
;
import
com.ruoyi.common.core.page.TableDataInfo
;
import
com.ruoyi.common.core.page.TableDataInfo
;
...
...
ruoyi-common/pom.xml
View file @
15102e6e
...
@@ -118,6 +118,10 @@
...
@@ -118,6 +118,10 @@
<groupId>
javax.servlet
</groupId>
<groupId>
javax.servlet
</groupId>
<artifactId>
javax.servlet-api
</artifactId>
<artifactId>
javax.servlet-api
</artifactId>
</dependency>
</dependency>
<dependency>
<groupId>
org.aspectj
</groupId>
<artifactId>
aspectjweaver
</artifactId>
</dependency>
</dependencies>
</dependencies>
...
...
ruoyi-common/src/main/java/com/ruoyi/common/annotation/SerialExecution.java
0 → 100644
View file @
15102e6e
package
com
.
ruoyi
.
common
.
annotation
;
import
java.lang.annotation.*
;
/**
* 若依框架适配 - 方法串行执行注解
* 标记该注解的方法,同一分组内串行执行,不同分组并行
*
* @author RuoYi
*/
@Target
({
ElementType
.
METHOD
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
SerialExecution
{
/**
* 串行分组(默认空,全局串行)
*/
String
group
()
default
""
;
/**
* 是否公平锁(按线程等待顺序执行)
*/
boolean
fair
()
default
false
;
}
\ No newline at end of file
ruoyi-common/src/main/java/com/ruoyi/common/aspectj/SerialExecutionAspect.java
0 → 100644
View file @
15102e6e
package
com
.
ruoyi
.
common
.
aspectj
;
import
com.ruoyi.common.annotation.SerialExecution
;
import
com.ruoyi.common.utils.StringUtils
;
import
org.aspectj.lang.ProceedingJoinPoint
;
import
org.aspectj.lang.annotation.Around
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.aspectj.lang.annotation.Pointcut
;
import
org.aspectj.lang.reflect.MethodSignature
;
import
org.springframework.stereotype.Component
;
import
java.lang.reflect.Method
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.locks.Lock
;
import
java.util.concurrent.locks.ReentrantLock
;
/**
* 若依框架适配 - 串行执行注解切面
* 参考若依 SysLogAspect 实现风格
*
* @author RuoYi
*/
@Aspect
@Component
public
class
SerialExecutionAspect
{
/**
* 分组锁缓存:key=分组名,value=锁对象
*/
private
final
Map
<
String
,
Lock
>
groupLockCache
=
new
ConcurrentHashMap
<>();
/**
* 切入点:拦截所有标记@SerialExecution的方法
*/
@Pointcut
(
"@annotation(com.ruoyi.common.annotation.SerialExecution)"
)
public
void
serialExecutionPointCut
()
{
}
/**
* 环绕通知:加锁执行,确保串行
*/
@Around
(
"serialExecutionPointCut()"
)
public
Object
around
(
ProceedingJoinPoint
joinPoint
)
throws
Throwable
{
// 1. 获取方法注解信息(参考若依日志切面的参数解析方式)
MethodSignature
signature
=
(
MethodSignature
)
joinPoint
.
getSignature
();
Method
method
=
signature
.
getMethod
();
SerialExecution
serialAnnotation
=
method
.
getAnnotation
(
SerialExecution
.
class
);
if
(
serialAnnotation
==
null
)
{
return
joinPoint
.
proceed
();
}
// 2. 解析分组(默认空=全局分组)
String
group
=
StringUtils
.
trimToEmpty
(
serialAnnotation
.
group
());
boolean
fair
=
serialAnnotation
.
fair
();
// 3. 获取/创建分组锁(复用若依 StringUtils 工具类)
Lock
lock
=
groupLockCache
.
computeIfAbsent
(
group
,
k
->
new
ReentrantLock
(
fair
));
// 4. 加锁执行(try-finally 确保锁释放,避免死锁)
try
{
lock
.
lock
();
// 执行原方法(若依业务方法的执行逻辑)
return
joinPoint
.
proceed
();
}
finally
{
lock
.
unlock
();
// 可选:若依日志记录(可接入若依的日志框架)
// LogUtils.info("串行方法执行完成,分组:{},方法:{}", group, method.getName());
}
}
}
\ No newline at end of file
ruoyi-inventory/src/main/java/com/ruoyi/inventory/controller/OutboundOrderItemsController.java
View file @
15102e6e
...
@@ -78,7 +78,16 @@ public class OutboundOrderItemsController extends BaseController
...
@@ -78,7 +78,16 @@ public class OutboundOrderItemsController extends BaseController
@PostMapping
@PostMapping
public
AjaxResult
add
(
@RequestBody
OutboundOrderItems
outboundOrderItems
)
public
AjaxResult
add
(
@RequestBody
OutboundOrderItems
outboundOrderItems
)
{
{
return
toAjax
(
outboundOrderItemsService
.
insertOutboundOrderItems
(
outboundOrderItems
));
try
{
// 调用业务层校验+插入逻辑
outboundOrderItemsService
.
insertOutboundOrderItems
(
outboundOrderItems
);
// 校验通过:返回成功(若依标准成功响应)
return
success
(
"新增出库单明细成功"
);
}
catch
(
Exception
e
)
{
// 校验失败:捕获异常,返回"库存被修改请重新确认"(前端弹窗用)
logger
.
error
(
"新增出库单明细失败"
,
e
);
return
error
(
"库存被修改请重新确认"
);
}
}
}
/**
/**
...
@@ -89,9 +98,19 @@ public class OutboundOrderItemsController extends BaseController
...
@@ -89,9 +98,19 @@ public class OutboundOrderItemsController extends BaseController
@PutMapping
@PutMapping
public
AjaxResult
edit
(
@RequestBody
OutboundOrderItems
outboundOrderItems
)
public
AjaxResult
edit
(
@RequestBody
OutboundOrderItems
outboundOrderItems
)
{
{
return
toAjax
(
outboundOrderItemsService
.
updateOutboundOrderItems
(
outboundOrderItems
));
try
{
// 调用业务层校验+插入逻辑
outboundOrderItemsService
.
updateOutboundOrderItems
(
outboundOrderItems
);
// 校验通过:返回成功(若依标准成功响应)
return
success
(
"新增出库单明细成功"
);
}
catch
(
Exception
e
)
{
// 校验失败:捕获异常,返回"库存被修改请重新确认"(前端弹窗用)
logger
.
error
(
"新增出库单明细失败"
,
e
);
return
error
(
"库存被修改请重新确认"
);
}
}
}
/**
/**
* 删除出库单明细
* 删除出库单明细
*/
*/
...
...
ruoyi-inventory/src/main/java/com/ruoyi/inventory/controller/OutboundOrdersController.java
View file @
15102e6e
...
@@ -2,6 +2,8 @@ package com.ruoyi.inventory.controller;
...
@@ -2,6 +2,8 @@ package com.ruoyi.inventory.controller;
import
java.util.List
;
import
java.util.List
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpServletResponse
;
import
com.ruoyi.inventory.domain.Inventory
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.GetMapping
;
...
@@ -70,6 +72,17 @@ public class OutboundOrdersController extends BaseController
...
@@ -70,6 +72,17 @@ public class OutboundOrdersController extends BaseController
}
}
/**
/**
* 出货
*/
@PreAuthorize
(
"@ss.hasPermi('inventory:inventory:edit')"
)
@Log
(
title
=
"出货"
,
businessType
=
BusinessType
.
UPDATE
)
@PostMapping
(
"/ship"
)
public
AjaxResult
Ship
(
@RequestBody
OutboundOrders
outboundOrders
)
{
return
toAjax
(
outboundOrdersService
.
ship
(
outboundOrders
));
}
/**
* 新增出库单主
* 新增出库单主
*/
*/
@PreAuthorize
(
"@ss.hasPermi('inventory:orders:add')"
)
@PreAuthorize
(
"@ss.hasPermi('inventory:orders:add')"
)
...
...
ruoyi-inventory/src/main/java/com/ruoyi/inventory/domain/OutboundOrderItems.java
View file @
15102e6e
...
@@ -40,6 +40,10 @@ public class OutboundOrderItems extends BaseEntity
...
@@ -40,6 +40,10 @@ public class OutboundOrderItems extends BaseEntity
@Excel
(
name
=
"库位ID 检索条件"
)
@Excel
(
name
=
"库位ID 检索条件"
)
private
String
locationId
;
private
String
locationId
;
/** 库存ID */
private
String
inventoryId
;
/** 计划数量 */
/** 计划数量 */
@Excel
(
name
=
"计划数量"
)
@Excel
(
name
=
"计划数量"
)
private
Long
plannedQuantity
;
private
Long
plannedQuantity
;
...
@@ -89,7 +93,15 @@ public class OutboundOrderItems extends BaseEntity
...
@@ -89,7 +93,15 @@ public class OutboundOrderItems extends BaseEntity
@Excel
(
name
=
"排序号"
)
@Excel
(
name
=
"排序号"
)
private
String
updateUserCode
;
private
String
updateUserCode
;
public
void
setId
(
String
id
)
public
String
getInventoryId
()
{
return
inventoryId
;
}
public
void
setInventoryId
(
String
inventoryId
)
{
this
.
inventoryId
=
inventoryId
;
}
public
void
setId
(
String
id
)
{
{
this
.
id
=
id
;
this
.
id
=
id
;
}
}
...
@@ -292,6 +304,7 @@ public class OutboundOrderItems extends BaseEntity
...
@@ -292,6 +304,7 @@ public class OutboundOrderItems extends BaseEntity
.
append
(
"createTime"
,
getCreateTime
())
.
append
(
"createTime"
,
getCreateTime
())
.
append
(
"createUserCode"
,
getCreateUserCode
())
.
append
(
"createUserCode"
,
getCreateUserCode
())
.
append
(
"updateTime"
,
getUpdateTime
())
.
append
(
"updateTime"
,
getUpdateTime
())
.
append
(
"inventoryId"
,
getInventoryId
())
.
append
(
"updateUserCode"
,
getUpdateUserCode
())
.
append
(
"updateUserCode"
,
getUpdateUserCode
())
.
toString
();
.
toString
();
}
}
...
...
ruoyi-inventory/src/main/java/com/ruoyi/inventory/domain/OutboundOrderLog.java
View file @
15102e6e
...
@@ -22,6 +22,9 @@ public class OutboundOrderLog extends BaseEntity
...
@@ -22,6 +22,9 @@ public class OutboundOrderLog extends BaseEntity
@Excel
(
name
=
"出货单号ID"
)
@Excel
(
name
=
"出货单号ID"
)
private
String
orderId
;
private
String
orderId
;
/** 库存ID */
private
String
inventoryId
;
/** 货物ID */
/** 货物ID */
@Excel
(
name
=
"货物ID"
)
@Excel
(
name
=
"货物ID"
)
private
String
materialId
;
private
String
materialId
;
...
@@ -81,7 +84,15 @@ public class OutboundOrderLog extends BaseEntity
...
@@ -81,7 +84,15 @@ public class OutboundOrderLog extends BaseEntity
this
.
warehouseId
=
warehouseId
;
this
.
warehouseId
=
warehouseId
;
}
}
public
String
getWarehouseId
()
public
String
getInventoryId
()
{
return
inventoryId
;
}
public
void
setInventoryId
(
String
inventoryId
)
{
this
.
inventoryId
=
inventoryId
;
}
public
String
getWarehouseId
()
{
{
return
warehouseId
;
return
warehouseId
;
}
}
...
@@ -137,6 +148,7 @@ public class OutboundOrderLog extends BaseEntity
...
@@ -137,6 +148,7 @@ public class OutboundOrderLog extends BaseEntity
.
append
(
"materialId"
,
getMaterialId
())
.
append
(
"materialId"
,
getMaterialId
())
.
append
(
"warehouseId"
,
getWarehouseId
())
.
append
(
"warehouseId"
,
getWarehouseId
())
.
append
(
"batchCode"
,
getBatchCode
())
.
append
(
"batchCode"
,
getBatchCode
())
.
append
(
"inventoryId"
,
getInventoryId
())
.
append
(
"actualQuantity"
,
getActualQuantity
())
.
append
(
"actualQuantity"
,
getActualQuantity
())
.
append
(
"itemStatus"
,
getItemStatus
())
.
append
(
"itemStatus"
,
getItemStatus
())
.
append
(
"isUsed"
,
getIsUsed
())
.
append
(
"isUsed"
,
getIsUsed
())
...
...
ruoyi-inventory/src/main/java/com/ruoyi/inventory/mapper/InventoryMapper.java
View file @
15102e6e
...
@@ -53,6 +53,8 @@ public interface InventoryMapper
...
@@ -53,6 +53,8 @@ public interface InventoryMapper
*/
*/
public
int
updateInventory
(
Inventory
inventory
);
public
int
updateInventory
(
Inventory
inventory
);
/**
/**
* 删除库存
* 删除库存
*
*
...
@@ -69,7 +71,7 @@ public interface InventoryMapper
...
@@ -69,7 +71,7 @@ public interface InventoryMapper
*/
*/
public
int
deleteInventoryByIds
(
String
[]
ids
);
public
int
deleteInventoryByIds
(
String
[]
ids
);
public
List
<
Inventory
>
listByMat
re
ialId
(
String
materialId
);
public
List
<
Inventory
>
listByMat
er
ialId
(
String
materialId
);
/**
/**
* @description: 获取库存盘点详细信息
* @description: 获取库存盘点详细信息
...
...
ruoyi-inventory/src/main/java/com/ruoyi/inventory/mapper/OutboundOrderLogMapper.java
View file @
15102e6e
package
com
.
ruoyi
.
inventory
.
mapper
;
package
com
.
ruoyi
.
inventory
.
mapper
;
import
java.util.List
;
import
java.util.List
;
import
com.ruoyi.inventory.domain.OutboundOrderItems
;
import
com.ruoyi.inventory.domain.OutboundOrderLog
;
import
com.ruoyi.inventory.domain.OutboundOrderLog
;
/**
/**
...
@@ -19,6 +21,7 @@ public interface OutboundOrderLogMapper
...
@@ -19,6 +21,7 @@ public interface OutboundOrderLogMapper
*/
*/
public
OutboundOrderLog
selectOutboundOrderLogById
(
String
id
);
public
OutboundOrderLog
selectOutboundOrderLogById
(
String
id
);
/**
/**
* 查询出库明细子(仅用于锁定数量统计)列表
* 查询出库明细子(仅用于锁定数量统计)列表
*
*
...
@@ -34,7 +37,8 @@ public interface OutboundOrderLogMapper
...
@@ -34,7 +37,8 @@ public interface OutboundOrderLogMapper
* @param outboundOrderLog 出库明细子(仅用于锁定数量统计)
* @param outboundOrderLog 出库明细子(仅用于锁定数量统计)
* @return 出库明细子(仅用于锁定数量统计)集合
* @return 出库明细子(仅用于锁定数量统计)集合
*/
*/
public
Long
selectLockedQuantity
(
OutboundOrderLog
outboundOrderLog
);
public
Long
selectLockedQuantityByInventory
(
String
id
);
/**
/**
* 新增出库明细子(仅用于锁定数量统计)
* 新增出库明细子(仅用于锁定数量统计)
...
@@ -66,6 +70,24 @@ public interface OutboundOrderLogMapper
...
@@ -66,6 +70,24 @@ public interface OutboundOrderLogMapper
* @param ids 需要删除的数据主键集合
* @param ids 需要删除的数据主键集合
* @return 结果
* @return 结果
*/
*/
public
int
deleteOutboundOrderLogByOrdersId
(
String
id
);
/**
* 批量删除出库明细子(仅用于锁定数量统计)
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public
int
deleteOutboundOrderLogByIds
(
String
[]
ids
);
public
int
deleteOutboundOrderLogByIds
(
String
[]
ids
);
/**
* 批量新增出库单明细
*
* @param outboundOrderItemsList 出库单明细列表
* @return 结果
*/
public
int
batchOutboundOrderLog
(
List
<
OutboundOrderLog
>
outboundOrderLogs
);
}
}
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/IInventoryService.java
View file @
15102e6e
...
@@ -2,21 +2,23 @@ package com.ruoyi.inventory.service;
...
@@ -2,21 +2,23 @@ package com.ruoyi.inventory.service;
import
java.util.List
;
import
java.util.List
;
import
com.ruoyi.common.annotation.SerialExecution
;
import
com.ruoyi.common.core.page.TableDataInfo
;
import
com.ruoyi.common.core.page.TableDataInfo
;
import
com.ruoyi.inventory.domain.Inventory
;
import
com.ruoyi.inventory.domain.Inventory
;
import
com.ruoyi.inventory.domain.OutboundOrderItems
;
import
com.ruoyi.inventory.domain.StocktakeItems
;
import
com.ruoyi.inventory.domain.StocktakeItems
;
/**
/**
* 库存Service接口
* 库存Service接口
*
*
* @author ruoyi
* @author ruoyi
* @date 2025-12-03
* @date 2025-12-03
*/
*/
public
interface
IInventoryService
public
interface
IInventoryService
{
{
/**
/**
* 查询库存
* 查询库存
*
*
* @param id 库存主键
* @param id 库存主键
* @return 库存
* @return 库存
*/
*/
...
@@ -24,7 +26,7 @@ public interface IInventoryService
...
@@ -24,7 +26,7 @@ public interface IInventoryService
/**
/**
* 查询库存列表
* 查询库存列表
*
*
* @param inventory 库存
* @param inventory 库存
* @return 库存集合
* @return 库存集合
*/
*/
...
@@ -34,7 +36,7 @@ public interface IInventoryService
...
@@ -34,7 +36,7 @@ public interface IInventoryService
/**
/**
* 新增库存
* 新增库存
*
*
* @param inventory 库存
* @param inventory 库存
* @return 结果
* @return 结果
*/
*/
...
@@ -49,15 +51,23 @@ public interface IInventoryService
...
@@ -49,15 +51,23 @@ public interface IInventoryService
public
int
insertInventoryList
(
List
<
Inventory
>
inventoryList
);
public
int
insertInventoryList
(
List
<
Inventory
>
inventoryList
);
/**
/**
* 修改库存
* 修改库存
*
*
* @param inventory 库存
* @param inventory 库存
* @return 结果
* @return 结果
*/
*/
public
int
updateInventory
(
Inventory
inventory
);
public
int
updateInventory
(
Inventory
inventory
);
int
RefreshInventory
(
List
<
String
>
inventoryIds
);
@SerialExecution
(
group
=
"inventoryRefresh"
,
fair
=
true
)
int
ship
(
List
<
OutboundOrderItems
>
outboundOrderItems
);
@SerialExecution
(
group
=
"inventoryRefresh"
,
fair
=
true
)
boolean
inventoryLockValidation
(
List
<
OutboundOrderItems
>
outboundOrderItems
);
/**
/**
* 批量删除库存
* 批量删除库存
*
*
* @param ids 需要删除的库存主键集合
* @param ids 需要删除的库存主键集合
* @return 结果
* @return 结果
*/
*/
...
@@ -65,14 +75,13 @@ public interface IInventoryService
...
@@ -65,14 +75,13 @@ public interface IInventoryService
/**
/**
* 删除库存信息
* 删除库存信息
*
*
* @param id 库存主键
* @param id 库存主键
* @return 结果
* @return 结果
*/
*/
public
int
deleteInventoryById
(
String
id
);
public
int
deleteInventoryById
(
String
id
);
public
List
<
Inventory
>
listByMatreialId
(
String
materialId
);
public
List
<
Inventory
>
listByMatreialId
(
String
materialId
);
/**
/**
* @description: 获取库存盘点详细信息
* @description: 获取库存盘点详细信息
* @author cs
* @author cs
...
@@ -80,4 +89,6 @@ public interface IInventoryService
...
@@ -80,4 +89,6 @@ public interface IInventoryService
* @version 1.0
* @version 1.0
*/
*/
public
List
<
StocktakeItems
>
selectstocktakeItemsList
();
public
List
<
StocktakeItems
>
selectstocktakeItemsList
();
}
}
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/IOutboundOrderLogService.java
View file @
15102e6e
...
@@ -35,7 +35,6 @@ public interface IOutboundOrderLogService
...
@@ -35,7 +35,6 @@ public interface IOutboundOrderLogService
*/
*/
public
int
insertOutboundOrderLog
(
OutboundOrderLog
outboundOrderLog
);
public
int
insertOutboundOrderLog
(
OutboundOrderLog
outboundOrderLog
);
Long
selectLockedQuantity
(
OutboundOrderLog
outboundOrderLog
);
/**
/**
* 修改出库明细子(仅用于锁定数量统计)
* 修改出库明细子(仅用于锁定数量统计)
...
...
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/IOutboundOrdersService.java
View file @
15102e6e
...
@@ -58,4 +58,13 @@ public interface IOutboundOrdersService
...
@@ -58,4 +58,13 @@ public interface IOutboundOrdersService
* @return 结果
* @return 结果
*/
*/
public
int
deleteOutboundOrdersById
(
String
id
);
public
int
deleteOutboundOrdersById
(
String
id
);
/**
* 出货
*
* @param id 出库单主主键
* @return 结果
*/
public
int
ship
(
OutboundOrders
outboundOrders
);
}
}
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/InventoryServiceImpl.java
View file @
15102e6e
package
com
.
ruoyi
.
inventory
.
service
.
impl
;
package
com
.
ruoyi
.
inventory
.
service
.
impl
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.List
;
import
java.util.UUID
;
import
java.util.UUID
;
import
java.util.stream.Collectors
;
import
com.ruoyi.common.annotation.SerialExecution
;
import
com.ruoyi.common.utils.DateUtils
;
import
com.ruoyi.common.utils.DateUtils
;
import
com.ruoyi.inventory.domain.OutboundOrderItems
;
import
com.ruoyi.inventory.domain.OutboundOrderLog
;
import
com.ruoyi.inventory.domain.OutboundOrderLog
;
import
com.ruoyi.inventory.domain.StocktakeItems
;
import
com.ruoyi.inventory.domain.StocktakeItems
;
import
com.ruoyi.inventory.mapper.OutboundOrderLogMapper
;
import
com.ruoyi.inventory.mapper.OutboundOrderLogMapper
;
import
org.springframework.beans.BeanUtils
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.lang3.SystemUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
import
com.ruoyi.inventory.mapper.InventoryMapper
;
import
com.ruoyi.inventory.mapper.InventoryMapper
;
...
@@ -16,7 +21,7 @@ import com.ruoyi.inventory.service.IInventoryService;
...
@@ -16,7 +21,7 @@ import com.ruoyi.inventory.service.IInventoryService;
/**
/**
* 库存Service业务层处理
* 库存Service业务层处理
*
*
* @author ruoyi
* @author ruoyi
* @date 2025-12-03
* @date 2025-12-03
*/
*/
...
@@ -30,7 +35,7 @@ public class InventoryServiceImpl implements IInventoryService
...
@@ -30,7 +35,7 @@ public class InventoryServiceImpl implements IInventoryService
/**
/**
* 查询库存
* 查询库存
*
*
* @param id 库存主键
* @param id 库存主键
* @return 库存
* @return 库存
*/
*/
...
@@ -42,7 +47,7 @@ public class InventoryServiceImpl implements IInventoryService
...
@@ -42,7 +47,7 @@ public class InventoryServiceImpl implements IInventoryService
/**
/**
* 查询库存列表
* 查询库存列表
*
*
* @param inventory 库存
* @param inventory 库存
* @return 库存
* @return 库存
*/
*/
...
@@ -52,19 +57,16 @@ public class InventoryServiceImpl implements IInventoryService
...
@@ -52,19 +57,16 @@ public class InventoryServiceImpl implements IInventoryService
return
inventoryMapper
.
selectInventoryList
(
inventory
);
return
inventoryMapper
.
selectInventoryList
(
inventory
);
}
}
@Override
@Override
public
Inventory
selectInventory
(
Inventory
inventory
)
public
Inventory
selectInventory
(
Inventory
inventory
)
{
{
Inventory
inventory1
=
inventoryMapper
.
selectInventory
(
inventory
);
return
inventoryMapper
.
selectInventory
(
inventory
);
OutboundOrderLog
outboundOrderLog
=
new
OutboundOrderLog
();
BeanUtils
.
copyProperties
(
inventory1
,
outboundOrderLog
);
inventory1
.
setLockedQuantity
(
outboundOrderLogMapper
.
selectLockedQuantity
(
outboundOrderLog
));
return
inventory1
;
}
}
/**
/**
* 新增库存
* 新增库存
*
*
* @param inventory 库存
* @param inventory 库存
* @return 结果
* @return 结果
*/
*/
...
@@ -72,6 +74,7 @@ public class InventoryServiceImpl implements IInventoryService
...
@@ -72,6 +74,7 @@ public class InventoryServiceImpl implements IInventoryService
public
int
insertInventory
(
Inventory
inventory
)
public
int
insertInventory
(
Inventory
inventory
)
{
{
inventory
.
setCreateTime
(
DateUtils
.
getNowDate
());
inventory
.
setCreateTime
(
DateUtils
.
getNowDate
());
inventory
.
setCreateBy
(
SystemUtils
.
getUserName
());
return
inventoryMapper
.
insertInventory
(
inventory
);
return
inventoryMapper
.
insertInventory
(
inventory
);
}
}
...
@@ -85,25 +88,80 @@ public class InventoryServiceImpl implements IInventoryService
...
@@ -85,25 +88,80 @@ public class InventoryServiceImpl implements IInventoryService
}
}
return
count
;
return
count
;
}
}
/**
/**
* 修改库存
* 修改库存
*
*
* @param inventory 库存
* @param inventory 库存
* @return 结果
* @return 结果
*/
*/
@Override
@Override
public
int
updateInventory
(
Inventory
inventory
)
public
int
updateInventory
(
Inventory
inventory
)
{
{
List
<
Inventory
>
inventoryList
=
Collections
.
singletonList
(
inventory
);
inventory
.
setUpdateTime
(
DateUtils
.
getNowDate
());
inventory
.
setUpdateTime
(
DateUtils
.
getNowDate
());
inventory
.
setUpdateBy
(
SystemUtils
.
getUserName
());
return
inventoryMapper
.
updateInventory
(
inventory
);
return
inventoryMapper
.
updateInventory
(
inventory
);
}
}
@SerialExecution
(
group
=
"inventoryRefresh"
,
fair
=
true
)
@Override
public
int
RefreshInventory
(
List
<
String
>
inventoryIds
)
{
for
(
String
inventoryId
:
inventoryIds
)
{
// 1. 空值前置校验:跳过空的循环项
if
(
inventoryId
==
null
)
{
continue
;
}
// 6. 查询锁定数量(优化:只查一次)
Long
lockedQuantity
=
outboundOrderLogMapper
.
selectLockedQuantityByInventory
(
inventoryId
);
Inventory
inventory
=
new
Inventory
();
inventory
.
setLockedQuantity
(
lockedQuantity
);
inventory
.
setId
(
inventoryId
);
inventoryMapper
.
updateInventory
(
inventory
);
}
return
1
;
}
@SerialExecution
(
group
=
"inventoryRefresh"
,
fair
=
true
)
@Override
public
int
ship
(
List
<
OutboundOrderItems
>
outboundOrderItems
)
{
if
(!
outboundOrderItems
.
isEmpty
())
{
for
(
OutboundOrderItems
outboundOrderItem
:
outboundOrderItems
)
{
OutboundOrderLog
outboundOrderLog
=
outboundOrderLogMapper
.
selectOutboundOrderLogById
(
outboundOrderItem
.
getId
());
Inventory
inventory
=
inventoryMapper
.
selectInventoryById
(
outboundOrderLog
.
getInventoryId
());
inventory
.
setQuantity
(
inventory
.
getQuantity
()-
outboundOrderItem
.
getActualQuantity
());
inventory
.
setLockedQuantity
(
inventory
.
getQuantity
()-
outboundOrderItem
.
getActualQuantity
());
if
(
inventory
.
getQuantity
()==
0
){
inventory
.
setInventoryStatus
(
0
l
);
}
updateInventory
(
inventory
);
}
}
return
1
;
}
@SerialExecution
(
group
=
"inventoryRefresh"
,
fair
=
true
)
@Override
public
boolean
inventoryLockValidation
(
List
<
OutboundOrderItems
>
outboundOrderItems
)
{
if
(!
outboundOrderItems
.
isEmpty
())
{
for
(
OutboundOrderItems
outboundOrderItem
:
outboundOrderItems
)
{
Inventory
inventory
=
inventoryMapper
.
selectInventoryById
(
outboundOrderItem
.
getInventoryId
());
if
(
inventory
.
getLockedQuantity
()+
outboundOrderItem
.
getActualQuantity
()>
inventory
.
getQuantity
()){
return
false
;
}
}
return
true
;
}
return
true
;
}
/**
/**
* 批量删除库存
* 批量删除库存
*
*
* @param ids 需要删除的库存主键
* @param ids 需要删除的库存主键
* @return 结果
* @return 结果
*/
*/
...
@@ -115,7 +173,7 @@ public class InventoryServiceImpl implements IInventoryService
...
@@ -115,7 +173,7 @@ public class InventoryServiceImpl implements IInventoryService
/**
/**
* 删除库存信息
* 删除库存信息
*
*
* @param id 库存主键
* @param id 库存主键
* @return 结果
* @return 结果
*/
*/
...
@@ -125,11 +183,19 @@ public class InventoryServiceImpl implements IInventoryService
...
@@ -125,11 +183,19 @@ public class InventoryServiceImpl implements IInventoryService
return
inventoryMapper
.
deleteInventoryById
(
id
);
return
inventoryMapper
.
deleteInventoryById
(
id
);
}
}
@SerialExecution
(
group
=
"inventoryRefresh"
,
fair
=
true
)
@Override
@Override
public
List
<
Inventory
>
listByMatreialId
(
String
materialId
)
{
public
List
<
Inventory
>
listByMatreialId
(
String
materialId
)
{
return
inventoryMapper
.
listByMatreialId
(
materialId
);
Inventory
inventory
=
new
Inventory
();
inventory
.
setMaterialId
(
materialId
);
List
<
String
>
inventoryIds
=
CollectionUtils
.
isEmpty
(
inventoryMapper
.
listByMaterialId
(
materialId
))
?
Collections
.
emptyList
()
// 空时返回空列表,避免后续NPE
:
inventoryMapper
.
listByMaterialId
(
materialId
).
stream
()
.
map
(
inventory2
->
inventory2
.
getId
())
// 提取ID(核心修正)
.
collect
(
Collectors
.
toList
());
RefreshInventory
(
inventoryIds
);
return
inventoryMapper
.
listByMaterialId
(
materialId
);
}
}
/**
/**
* @description: 获取库存盘点详细信息
* @description: 获取库存盘点详细信息
* @author cs
* @author cs
...
...
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/OutboundOrderItemsServiceImpl.java
View file @
15102e6e
package
com
.
ruoyi
.
inventory
.
service
.
impl
;
package
com
.
ruoyi
.
inventory
.
service
.
impl
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
import
com.ruoyi.common.utils.DateUtils
;
import
com.ruoyi.common.utils.DateUtils
;
import
com.ruoyi.inventory.domain.Inventory
;
import
com.ruoyi.inventory.domain.OutboundOrderLog
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
import
com.ruoyi.inventory.mapper.OutboundOrderItemsMapper
;
import
com.ruoyi.inventory.mapper.OutboundOrderItemsMapper
;
...
@@ -53,12 +49,7 @@ public class OutboundOrderItemsServiceImpl implements IOutboundOrderItemsService
...
@@ -53,12 +49,7 @@ public class OutboundOrderItemsServiceImpl implements IOutboundOrderItemsService
return
outboundOrderItemsMapper
.
selectOutboundOrderItemsList
(
outboundOrderItems
);
return
outboundOrderItemsMapper
.
selectOutboundOrderItemsList
(
outboundOrderItems
);
}
}
/**
* 新增出库单明细
*
* @param outboundOrderItemsInventory 出库单明细库存DTO
* @return 结果
*/
@Override
@Override
public
int
insertOutboundOrderItems
(
OutboundOrderItems
outboundOrderItems
)
public
int
insertOutboundOrderItems
(
OutboundOrderItems
outboundOrderItems
)
{
{
...
@@ -66,12 +57,7 @@ public class OutboundOrderItemsServiceImpl implements IOutboundOrderItemsService
...
@@ -66,12 +57,7 @@ public class OutboundOrderItemsServiceImpl implements IOutboundOrderItemsService
return
outboundOrderItemsMapper
.
insertOutboundOrderItems
(
outboundOrderItems
);
return
outboundOrderItemsMapper
.
insertOutboundOrderItems
(
outboundOrderItems
);
}
}
/**
* 修改出库单明细
*
* @param outboundOrderItemsInventory 出库单明细库存DTO
* @return 结果
*/
@Override
@Override
public
int
updateOutboundOrderItems
(
OutboundOrderItems
outboundOrderItems
)
public
int
updateOutboundOrderItems
(
OutboundOrderItems
outboundOrderItems
)
{
{
...
...
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/OutboundOrderLogServiceImpl.java
View file @
15102e6e
...
@@ -54,10 +54,6 @@ public class OutboundOrderLogServiceImpl implements IOutboundOrderLogService
...
@@ -54,10 +54,6 @@ public class OutboundOrderLogServiceImpl implements IOutboundOrderLogService
{
{
return
outboundOrderLogMapper
.
insertOutboundOrderLog
(
outboundOrderLog
);
return
outboundOrderLogMapper
.
insertOutboundOrderLog
(
outboundOrderLog
);
}
}
@Override
public
Long
selectLockedQuantity
(
OutboundOrderLog
outboundOrderLog
){
return
outboundOrderLogMapper
.
selectLockedQuantity
(
outboundOrderLog
);
}
/**
/**
* 修改出库明细子(仅用于锁定数量统计)
* 修改出库明细子(仅用于锁定数量统计)
*
*
...
...
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/OutboundOrdersServiceImpl.java
View file @
15102e6e
package
com
.
ruoyi
.
inventory
.
service
.
impl
;
package
com
.
ruoyi
.
inventory
.
service
.
impl
;
import
java.util.List
;
import
java.util.List
;
import
com.ruoyi.common.annotation.SerialExecution
;
import
com.ruoyi.common.utils.DateUtils
;
import
com.ruoyi.common.utils.DateUtils
;
import
com.ruoyi.inventory.domain.Inventory
;
import
com.ruoyi.inventory.domain.OutboundOrderLog
;
import
com.ruoyi.inventory.mapper.InventoryMapper
;
import
com.ruoyi.inventory.mapper.OutboundOrderItemsMapper
;
import
com.ruoyi.inventory.mapper.OutboundOrderLogMapper
;
import
org.apache.commons.lang3.SystemUtils
;
import
org.springframework.beans.BeanUtils
;
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
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.UUID
;
import
com.ruoyi.common.utils.StringUtils
;
import
com.ruoyi.common.utils.StringUtils
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.transaction.annotation.Transactional
;
import
com.ruoyi.inventory.domain.OutboundOrderItems
;
import
com.ruoyi.inventory.domain.OutboundOrderItems
;
...
@@ -14,19 +25,26 @@ import com.ruoyi.inventory.service.IOutboundOrdersService;
...
@@ -14,19 +25,26 @@ import com.ruoyi.inventory.service.IOutboundOrdersService;
/**
/**
* 出库单主Service业务层处理
* 出库单主Service业务层处理
*
*
* @author ruoyi
* @author ruoyi
* @date 2025-12-03
* @date 2025-12-03
*/
*/
@Service
@Service
public
class
OutboundOrdersServiceImpl
implements
IOutboundOrdersService
public
class
OutboundOrdersServiceImpl
implements
IOutboundOrdersService
{
{
@Autowired
@Autowired
private
OutboundOrdersMapper
outboundOrdersMapper
;
private
OutboundOrdersMapper
outboundOrdersMapper
;
@Autowired
private
OutboundOrderItemsMapper
outboundOrderItemsMapper
;
@Autowired
private
OutboundOrderLogMapper
outboundOrderLogMapper
;
@Autowired
private
InventoryServiceImpl
inventoryService
;
/**
/**
* 查询出库单主
* 查询出库单主
*
*
* @param id 出库单主主键
* @param id 出库单主主键
* @return 出库单主
* @return 出库单主
*/
*/
...
@@ -39,7 +57,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
...
@@ -39,7 +57,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
/**
/**
* 查询出库单主列表
* 查询出库单主列表
*
*
* @param outboundOrders 出库单主
* @param outboundOrders 出库单主
* @return 出库单主
* @return 出库单主
*/
*/
...
@@ -51,7 +69,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
...
@@ -51,7 +69,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
/**
/**
* 新增出库单主
* 新增出库单主
*
*
* @param outboundOrders 出库单主
* @param outboundOrders 出库单主
* @return 结果
* @return 结果
*/
*/
...
@@ -60,6 +78,8 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
...
@@ -60,6 +78,8 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
public
int
insertOutboundOrders
(
OutboundOrders
outboundOrders
)
public
int
insertOutboundOrders
(
OutboundOrders
outboundOrders
)
{
{
outboundOrders
.
setCreateTime
(
DateUtils
.
getNowDate
());
outboundOrders
.
setCreateTime
(
DateUtils
.
getNowDate
());
outboundOrders
.
setCreateBy
(
SystemUtils
.
getUserName
());
outboundOrders
.
setId
(
UUID
.
randomUUID
().
toString
());
int
rows
=
outboundOrdersMapper
.
insertOutboundOrders
(
outboundOrders
);
int
rows
=
outboundOrdersMapper
.
insertOutboundOrders
(
outboundOrders
);
insertOutboundOrderItems
(
outboundOrders
);
insertOutboundOrderItems
(
outboundOrders
);
return
rows
;
return
rows
;
...
@@ -67,7 +87,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
...
@@ -67,7 +87,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
/**
/**
* 修改出库单主
* 修改出库单主
*
*
* @param outboundOrders 出库单主
* @param outboundOrders 出库单主
* @return 结果
* @return 结果
*/
*/
...
@@ -77,13 +97,14 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
...
@@ -77,13 +97,14 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
{
{
outboundOrders
.
setUpdateTime
(
DateUtils
.
getNowDate
());
outboundOrders
.
setUpdateTime
(
DateUtils
.
getNowDate
());
outboundOrdersMapper
.
deleteOutboundOrderItemsByOrderId
(
outboundOrders
.
getId
());
outboundOrdersMapper
.
deleteOutboundOrderItemsByOrderId
(
outboundOrders
.
getId
());
outboundOrderLogMapper
.
deleteOutboundOrderLogByOrdersId
(
outboundOrders
.
getId
());
insertOutboundOrderItems
(
outboundOrders
);
insertOutboundOrderItems
(
outboundOrders
);
return
outboundOrdersMapper
.
updateOutboundOrders
(
outboundOrders
);
return
outboundOrdersMapper
.
updateOutboundOrders
(
outboundOrders
);
}
}
/**
/**
* 批量删除出库单主
* 批量删除出库单主
*
*
* @param ids 需要删除的出库单主主键
* @param ids 需要删除的出库单主主键
* @return 结果
* @return 结果
*/
*/
...
@@ -97,7 +118,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
...
@@ -97,7 +118,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
/**
/**
* 删除出库单主信息
* 删除出库单主信息
*
*
* @param id 出库单主主键
* @param id 出库单主主键
* @return 结果
* @return 结果
*/
*/
...
@@ -108,26 +129,88 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
...
@@ -108,26 +129,88 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
outboundOrdersMapper
.
deleteOutboundOrderItemsByOrderId
(
id
);
outboundOrdersMapper
.
deleteOutboundOrderItemsByOrderId
(
id
);
return
outboundOrdersMapper
.
deleteOutboundOrdersById
(
id
);
return
outboundOrdersMapper
.
deleteOutboundOrdersById
(
id
);
}
}
@SerialExecution
(
group
=
"inventoryRefresh"
,
fair
=
true
)
@Override
public
int
ship
(
OutboundOrders
outboundOrders
)
{
OutboundOrderItems
outboundOrderItems1
=
new
OutboundOrderItems
();
outboundOrderItems1
.
setOrderId
(
outboundOrders
.
getId
());
List
<
OutboundOrderItems
>
outboundOrderItems
=
outboundOrderItemsMapper
.
selectOutboundOrderItemsList
(
outboundOrderItems1
);
List
<
OutboundOrderItems
>
outboundOrderItems2
=
outboundOrderItems
;
OutboundOrderLog
outboundOrderLog
=
new
OutboundOrderLog
();
for
(
OutboundOrderItems
outboundOrderItem
:
outboundOrderItems
)
{
outboundOrderItem
.
setItemStatus
(
3
l
);
outboundOrderItemsMapper
.
updateOutboundOrderItems
(
outboundOrderItem
);
outboundOrderLog
.
setId
(
outboundOrderItem
.
getId
());
outboundOrderLog
.
setItemStatus
(
outboundOrderItem
.
getItemStatus
());
outboundOrderLogMapper
.
updateOutboundOrderLog
(
outboundOrderLog
);
}
outboundOrders
.
setId
(
outboundOrders
.
getId
());
outboundOrders
.
setOrderStatus
(
3
l
);
outboundOrders
.
setUpdateTime
(
DateUtils
.
getNowDate
());
outboundOrders
.
setUpdateBy
(
SystemUtils
.
getUserName
());
outboundOrdersMapper
.
updateOutboundOrders
(
outboundOrders
);
inventoryService
.
ship
(
outboundOrderItems2
);
return
1
;
}
/**
/**
* 新增出库单明细信息
* 新增出库单明细信息
*
*
* @param outboundOrders 出库单主对象
* @param outboundOrders 出库单主对象
*/
*/
public
void
insertOutboundOrderItems
(
OutboundOrders
outboundOrders
)
public
void
insertOutboundOrderItems
(
OutboundOrders
outboundOrders
)
{
{
List
<
OutboundOrderItems
>
outboundOrderItemsList
=
outboundOrders
.
getOutboundOrderItemsList
();
List
<
OutboundOrderItems
>
outboundOrderItemsList
=
outboundOrders
.
getOutboundOrderItemsList
();
String
id
=
outboundOrders
.
getId
();
String
id
=
outboundOrders
.
getId
();
if
(
StringUtils
.
isNotNull
(
outboundOrderItemsList
))
// 1. 先做空列表校验(提前返回,避免无效逻辑)
{
if
(
outboundOrderItemsList
==
null
||
outboundOrderItemsList
.
isEmpty
())
{
for
(
OutboundOrderItems
outboundOrderItems
:
outboundOrderItemsList
)
return
;
{
}
outboundOrderItems
.
setOrderId
(
id
);
}
// 2. 库存校验:失败时抛异常(核心修正:! 取反 + 异常抛出后代码立即终止)
if
(
outboundOrderItemsList
.
size
()
>
0
)
boolean
isValid
=
inventoryService
.
inventoryLockValidation
(
outboundOrderItemsList
);
{
if
(!
isValid
)
{
// 校验失败(返回false)时抛异常
outboundOrdersMapper
.
batchOutboundOrderItems
(
outboundOrderItemsList
);
throw
new
RuntimeException
(
"库存被修改请重新确认"
);
// 抛异常后,方法立即停止运行
}
}
// 2. 为明细设置订单ID和主键ID
for
(
OutboundOrderItems
items
:
outboundOrderItemsList
)
{
items
.
setOrderId
(
id
);
// 生成无横线的UUID作为主键
items
.
setId
(
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
));
}
// 3. 批量插入出库单明细
outboundOrdersMapper
.
batchOutboundOrderItems
(
outboundOrderItemsList
);
// 4. 正确拷贝明细列表到日志列表(修复核心错误:遍历逐个拷贝)
List
<
String
>
inventoryIds
=
new
ArrayList
<>();
List
<
OutboundOrderLog
>
outboundOrderLogs
=
new
ArrayList
<>();
for
(
OutboundOrderItems
items
:
outboundOrderItemsList
)
{
OutboundOrderLog
log
=
new
OutboundOrderLog
();
BeanUtils
.
copyProperties
(
items
,
log
);
// 单个对象属性拷贝
outboundOrderLogs
.
add
(
log
);
inventoryIds
.
add
(
log
.
getInventoryId
());
deleteOutboundOrdersById
(
items
.
getId
());
}
// 5. 非空校验后插入日志(避免空列表触发SQL语法错误)
if
(!
outboundOrderLogs
.
isEmpty
())
{
outboundOrderLogMapper
.
batchOutboundOrderLog
(
outboundOrderLogs
);
}
// 7. 非空校验后刷新库存
if
(!
inventoryIds
.
isEmpty
())
{
inventoryService
.
RefreshInventory
(
inventoryIds
);
}
}
}
}
}
}
ruoyi-inventory/src/main/resources/mapper/inventory/InventoryMapper.xml
View file @
15102e6e
...
@@ -123,9 +123,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -123,9 +123,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include
refid=
"selectInventoryVo"
/>
<include
refid=
"selectInventoryVo"
/>
where id = #{id}
where id = #{id}
</select>
</select>
<select
id=
"listByMat
re
ialId"
parameterType=
"String"
resultMap=
"InventoryResult"
>
<select
id=
"listByMat
er
ialId"
parameterType=
"String"
resultMap=
"InventoryResult"
>
<include
refid=
"selectInventoryVo"
/>
<include
refid=
"selectInventoryVo"
/>
where material_id = #{materialId}
where 1=1
<if
test=
"materialId != null and materialId.trim() != ''"
>
and material_id = #{materialId}
</if>
<![CDATA[
and inventory_status = '1'
and quantity >
locked_quantity
]]>
</select>
</select>
<insert
id=
"insertInventory"
parameterType=
"Inventory"
>
<insert
id=
"insertInventory"
parameterType=
"Inventory"
>
insert into inventory
insert into inventory
...
...
ruoyi-inventory/src/main/resources/mapper/inventory/OutboundOrderItemsMapper.xml
View file @
15102e6e
...
@@ -11,6 +11,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -11,6 +11,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result
property=
"batchCode"
column=
"batch_code"
/>
<result
property=
"batchCode"
column=
"batch_code"
/>
<result
property=
"warehouseId"
column=
"warehouse_id"
/>
<result
property=
"warehouseId"
column=
"warehouse_id"
/>
<result
property=
"locationId"
column=
"location_id"
/>
<result
property=
"locationId"
column=
"location_id"
/>
<result
property=
"inventoryId"
column=
"inventory_id"
/>
<result
property=
"plannedQuantity"
column=
"planned_quantity"
/>
<result
property=
"plannedQuantity"
column=
"planned_quantity"
/>
<result
property=
"actualQuantity"
column=
"actual_quantity"
/>
<result
property=
"actualQuantity"
column=
"actual_quantity"
/>
<result
property=
"divisor"
column=
"divisor"
/>
<result
property=
"divisor"
column=
"divisor"
/>
...
@@ -29,7 +30,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -29,7 +30,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
</resultMap>
<sql
id=
"selectOutboundOrderItemsVo"
>
<sql
id=
"selectOutboundOrderItemsVo"
>
select id, order_id, material_id, batch_code, warehouse_id, location_id, planned_quantity, actual_quantity, divisor, label_color, voucher_number, item_status, shipped_at, shipped_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code from outbound_order_items
select id, order_id, material_id, batch_code, warehouse_id, location_id,
inventory_id,
planned_quantity, actual_quantity, divisor, label_color, voucher_number, item_status, shipped_at, shipped_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code from outbound_order_items
</sql>
</sql>
<select
id=
"selectOutboundOrderItemsList"
parameterType=
"OutboundOrderItems"
resultMap=
"OutboundOrderItemsResult"
>
<select
id=
"selectOutboundOrderItemsList"
parameterType=
"OutboundOrderItems"
resultMap=
"OutboundOrderItemsResult"
>
...
@@ -40,6 +41,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -40,6 +41,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"batchCode != null and batchCode != ''"
>
and batch_code = #{batchCode}
</if>
<if
test=
"batchCode != null and batchCode != ''"
>
and batch_code = #{batchCode}
</if>
<if
test=
"warehouseId != null and warehouseId != ''"
>
and warehouse_id = #{warehouseId}
</if>
<if
test=
"warehouseId != null and warehouseId != ''"
>
and warehouse_id = #{warehouseId}
</if>
<if
test=
"locationId != null and locationId != ''"
>
and location_id = #{locationId}
</if>
<if
test=
"locationId != null and locationId != ''"
>
and location_id = #{locationId}
</if>
<if
test=
"inventoryId != null and inventoryId != ''"
>
and inventory_id = #{inventoryId}
</if>
<if
test=
"plannedQuantity != null "
>
and planned_quantity = #{plannedQuantity}
</if>
<if
test=
"plannedQuantity != null "
>
and planned_quantity = #{plannedQuantity}
</if>
<if
test=
"actualQuantity != null "
>
and actual_quantity = #{actualQuantity}
</if>
<if
test=
"actualQuantity != null "
>
and actual_quantity = #{actualQuantity}
</if>
<if
test=
"divisor != null "
>
and divisor = #{divisor}
</if>
<if
test=
"divisor != null "
>
and divisor = #{divisor}
</if>
...
@@ -69,6 +71,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -69,6 +71,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"batchCode != null"
>
batch_code,
</if>
<if
test=
"batchCode != null"
>
batch_code,
</if>
<if
test=
"warehouseId != null"
>
warehouse_id,
</if>
<if
test=
"warehouseId != null"
>
warehouse_id,
</if>
<if
test=
"locationId != null"
>
location_id,
</if>
<if
test=
"locationId != null"
>
location_id,
</if>
<if
test=
"inventoryId != null"
>
inventory_id,
</if>
<if
test=
"plannedQuantity != null"
>
planned_quantity,
</if>
<if
test=
"plannedQuantity != null"
>
planned_quantity,
</if>
<if
test=
"actualQuantity != null"
>
actual_quantity,
</if>
<if
test=
"actualQuantity != null"
>
actual_quantity,
</if>
<if
test=
"divisor != null"
>
divisor,
</if>
<if
test=
"divisor != null"
>
divisor,
</if>
...
@@ -92,6 +95,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -92,6 +95,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"batchCode != null"
>
#{batchCode},
</if>
<if
test=
"batchCode != null"
>
#{batchCode},
</if>
<if
test=
"warehouseId != null"
>
#{warehouseId},
</if>
<if
test=
"warehouseId != null"
>
#{warehouseId},
</if>
<if
test=
"locationId != null"
>
#{locationId},
</if>
<if
test=
"locationId != null"
>
#{locationId},
</if>
<if
test=
"inventoryId != null"
>
#{inventoryId},
</if>
<if
test=
"plannedQuantity != null"
>
#{plannedQuantity},
</if>
<if
test=
"plannedQuantity != null"
>
#{plannedQuantity},
</if>
<if
test=
"actualQuantity != null"
>
#{actualQuantity},
</if>
<if
test=
"actualQuantity != null"
>
#{actualQuantity},
</if>
<if
test=
"divisor != null"
>
#{divisor},
</if>
<if
test=
"divisor != null"
>
#{divisor},
</if>
...
@@ -118,6 +122,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -118,6 +122,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"batchCode != null"
>
batch_code = #{batchCode},
</if>
<if
test=
"batchCode != null"
>
batch_code = #{batchCode},
</if>
<if
test=
"warehouseId != null"
>
warehouse_id = #{warehouseId},
</if>
<if
test=
"warehouseId != null"
>
warehouse_id = #{warehouseId},
</if>
<if
test=
"locationId != null"
>
location_id = #{locationId},
</if>
<if
test=
"locationId != null"
>
location_id = #{locationId},
</if>
<if
test=
"inventoryId != null"
>
inventory_id = #{inventoryId},
</if>
<if
test=
"plannedQuantity != null"
>
planned_quantity = #{plannedQuantity},
</if>
<if
test=
"plannedQuantity != null"
>
planned_quantity = #{plannedQuantity},
</if>
<if
test=
"actualQuantity != null"
>
actual_quantity = #{actualQuantity},
</if>
<if
test=
"actualQuantity != null"
>
actual_quantity = #{actualQuantity},
</if>
<if
test=
"divisor != null"
>
divisor = #{divisor},
</if>
<if
test=
"divisor != null"
>
divisor = #{divisor},
</if>
...
...
ruoyi-inventory/src/main/resources/mapper/inventory/OutboundOrderLogMapper.xml
View file @
15102e6e
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
<resultMap
type=
"OutboundOrderLog"
id=
"OutboundOrderLogResult"
>
<resultMap
type=
"OutboundOrderLog"
id=
"OutboundOrderLogResult"
>
<result
property=
"id"
column=
"id"
/>
<result
property=
"id"
column=
"id"
/>
<result
property=
"orderId"
column=
"order_id"
/>
<result
property=
"orderId"
column=
"order_id"
/>
<result
property=
"inventoryId"
column=
"inventory_id"
/>
<result
property=
"materialId"
column=
"material_id"
/>
<result
property=
"materialId"
column=
"material_id"
/>
<result
property=
"warehouseId"
column=
"warehouse_id"
/>
<result
property=
"warehouseId"
column=
"warehouse_id"
/>
<result
property=
"batchCode"
column=
"batch_code"
/>
<result
property=
"batchCode"
column=
"batch_code"
/>
...
@@ -15,8 +16,9 @@
...
@@ -15,8 +16,9 @@
<result
property=
"isUsed"
column=
"is_used"
/>
<result
property=
"isUsed"
column=
"is_used"
/>
</resultMap>
</resultMap>
<!-- 补充inventory_id到查询字段中 -->
<sql
id=
"selectOutboundOrderLogVo"
>
<sql
id=
"selectOutboundOrderLogVo"
>
select id, order_id, material_id, warehouse_id, batch_code, actual_quantity, item_status, is_used
select id, order_id,
inventory_id,
material_id, warehouse_id, batch_code, actual_quantity, item_status, is_used
from outbound_order_log
from outbound_order_log
</sql>
</sql>
...
@@ -24,6 +26,7 @@
...
@@ -24,6 +26,7 @@
<include
refid=
"selectOutboundOrderLogVo"
/>
<include
refid=
"selectOutboundOrderLogVo"
/>
<where>
<where>
<if
test=
"orderId != null and orderId != ''"
>
and order_id = #{orderId}
</if>
<if
test=
"orderId != null and orderId != ''"
>
and order_id = #{orderId}
</if>
<if
test=
"inventoryId != null and inventoryId != ''"
>
and inventory_id = #{inventoryId}
</if>
<if
test=
"materialId != null and materialId != ''"
>
and material_id = #{materialId}
</if>
<if
test=
"materialId != null and materialId != ''"
>
and material_id = #{materialId}
</if>
<if
test=
"warehouseId != null and warehouseId != ''"
>
and warehouse_id = #{warehouseId}
</if>
<if
test=
"warehouseId != null and warehouseId != ''"
>
and warehouse_id = #{warehouseId}
</if>
<if
test=
"batchCode != null and batchCode != ''"
>
and batch_code = #{batchCode}
</if>
<if
test=
"batchCode != null and batchCode != ''"
>
and batch_code = #{batchCode}
</if>
...
@@ -33,26 +36,39 @@
...
@@ -33,26 +36,39 @@
</where>
</where>
</select>
</select>
<select
id=
"selectLockedQuantity"
parameterType=
"OutboundOrderLog"
resultType=
"java.lang.Long"
>
<select
id=
"deleteLog"
parameterType=
"OutboundOrderLog"
resultMap=
"OutboundOrderLogResult"
>
select ifnull(sum(actual_quantity), 0)
delete from outbound_order_log
from outbound_order_log
<where>
<where>
<if
test=
"materialId != null and materialId != ''"
>
and material_id = #{materialId}
</if>
<if
test=
"materialId != null and materialId != ''"
>
and material_id = #{materialId}
</if>
<if
test=
"warehouseId != null and warehouseId != ''"
>
and warehouse_id = #{warehouseId}
</if>
<if
test=
"warehouseId != null and warehouseId != ''"
>
and warehouse_id = #{warehouseId}
</if>
<if
test=
"batchCode != null and batchCode != ''"
>
and batch_code = #{batchCode}
</if>
<if
test=
"batchCode != null and batchCode != ''"
>
and batch_code = #{batchCode}
</if>
<if
test=
"itemStatus != null "
>
and item_status = #{itemStatus}
</if>
<!-- 补充inventory_id条件 -->
<if
test=
"inventoryId != null and inventoryId != ''"
>
and inventory_id = #{inventoryId}
</if>
</where>
</where>
</select>
</select>
<!-- 修正参数错误:原#{id}改为#{inventoryId} -->
<select
id=
"selectLockedQuantityByInventory"
parameterType=
"OutboundOrderLog"
resultType=
"java.lang.Long"
>
select ifnull(sum(actual_quantity), 0)
from outbound_order_log
where item_status=1
<if
test=
"inventoryId != null and inventoryId != ''"
>
and inventory_id = #{inventoryId}
</if>
</select>
<select
id=
"selectOutboundOrderLogById"
parameterType=
"String"
resultMap=
"OutboundOrderLogResult"
>
<select
id=
"selectOutboundOrderLogById"
parameterType=
"String"
resultMap=
"OutboundOrderLogResult"
>
<include
refid=
"selectOutboundOrderLogVo"
/>
<include
refid=
"selectOutboundOrderLogVo"
/>
where id = #{id}
where id = #{id}
</select>
</select>
<!-- 插入语句补充inventory_id -->
<insert
id=
"insertOutboundOrderLog"
parameterType=
"OutboundOrderLog"
>
<insert
id=
"insertOutboundOrderLog"
parameterType=
"OutboundOrderLog"
>
insert into outbound_order_log
insert into outbound_order_log
<trim
prefix=
"("
suffix=
")"
suffixOverrides=
","
>
<trim
prefix=
"("
suffix=
")"
suffixOverrides=
","
>
<if
test=
"id != null"
>
id,
</if>
<if
test=
"id != null"
>
id,
</if>
<if
test=
"orderId != null"
>
order_id,
</if>
<if
test=
"orderId != null"
>
order_id,
</if>
<if
test=
"inventoryId != null"
>
inventory_id,
</if>
<if
test=
"materialId != null"
>
material_id,
</if>
<if
test=
"materialId != null"
>
material_id,
</if>
<if
test=
"warehouseId != null"
>
warehouse_id,
</if>
<if
test=
"warehouseId != null"
>
warehouse_id,
</if>
<if
test=
"batchCode != null"
>
batch_code,
</if>
<if
test=
"batchCode != null"
>
batch_code,
</if>
...
@@ -63,6 +79,7 @@
...
@@ -63,6 +79,7 @@
<trim
prefix=
"values ("
suffix=
")"
suffixOverrides=
","
>
<trim
prefix=
"values ("
suffix=
")"
suffixOverrides=
","
>
<if
test=
"id != null"
>
#{id},
</if>
<if
test=
"id != null"
>
#{id},
</if>
<if
test=
"orderId != null"
>
#{orderId},
</if>
<if
test=
"orderId != null"
>
#{orderId},
</if>
<if
test=
"inventoryId != null"
>
#{inventoryId},
</if>
<if
test=
"materialId != null"
>
#{materialId},
</if>
<if
test=
"materialId != null"
>
#{materialId},
</if>
<if
test=
"warehouseId != null"
>
#{warehouseId},
</if>
<if
test=
"warehouseId != null"
>
#{warehouseId},
</if>
<if
test=
"batchCode != null"
>
#{batchCode},
</if>
<if
test=
"batchCode != null"
>
#{batchCode},
</if>
...
@@ -72,10 +89,12 @@
...
@@ -72,10 +89,12 @@
</trim>
</trim>
</insert>
</insert>
<!-- 更新语句补充inventory_id -->
<update
id=
"updateOutboundOrderLog"
parameterType=
"OutboundOrderLog"
>
<update
id=
"updateOutboundOrderLog"
parameterType=
"OutboundOrderLog"
>
update outbound_order_log
update outbound_order_log
<trim
prefix=
"SET"
suffixOverrides=
","
>
<trim
prefix=
"SET"
suffixOverrides=
","
>
<if
test=
"orderId != null"
>
order_id = #{orderId},
</if>
<if
test=
"orderId != null"
>
order_id = #{orderId},
</if>
<if
test=
"inventoryId != null"
>
inventory_id = #{inventoryId},
</if>
<if
test=
"materialId != null"
>
material_id = #{materialId},
</if>
<if
test=
"materialId != null"
>
material_id = #{materialId},
</if>
<if
test=
"warehouseId != null"
>
warehouse_id = #{warehouseId},
</if>
<if
test=
"warehouseId != null"
>
warehouse_id = #{warehouseId},
</if>
<if
test=
"batchCode != null"
>
batch_code = #{batchCode},
</if>
<if
test=
"batchCode != null"
>
batch_code = #{batchCode},
</if>
...
@@ -90,10 +109,39 @@
...
@@ -90,10 +109,39 @@
delete from outbound_order_log where id = #{id}
delete from outbound_order_log where id = #{id}
</delete>
</delete>
<delete
id=
"deleteOutboundOrderLogByIds"
parameterType=
"String"
>
<delete
id=
"deleteOutboundOrderLogByOrdersId"
parameterType=
"String"
>
delete from outbound_order_log where id in
delete from outbound_order_log where order_id = #{id}
<foreach
item=
"id"
collection=
"array"
open=
"("
separator=
","
close=
")"
>
#{id}
</foreach>
</delete>
</delete>
<!-- 批量插入补充inventory_id -->
<insert
id=
"batchOutboundOrderLog"
>
<!-- 增加非空判断,避免空列表导致SQL语法错误 -->
<if
test=
"list != null and list.size() > 0"
>
insert into outbound_order_log(
id,
order_id,
inventory_id,
<!-- 新增 -->
material_id,
warehouse_id,
batch_code,
<!-- 对应实体类batchCode -->
actual_quantity,
item_status,
is_used
) values
<foreach
item=
"item"
index=
"index"
collection=
"list"
separator=
","
>
(
#{item.id},
#{item.orderId},
#{item.inventoryId},
#{item.materialId},
#{item.warehouseId},
#{item.batchCode},
#{item.actualQuantity},
#{item.itemStatus},
#{item.isUsed}
)
</foreach>
</if>
</insert>
</mapper>
</mapper>
\ No newline at end of file
ruoyi-inventory/src/main/resources/mapper/inventory/OutboundOrdersMapper.xml
View file @
15102e6e
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"com.ruoyi.inventory.mapper.OutboundOrdersMapper"
>
<mapper
namespace=
"com.ruoyi.inventory.mapper.OutboundOrdersMapper"
>
<resultMap
type=
"OutboundOrders"
id=
"OutboundOrdersResult"
>
<resultMap
type=
"OutboundOrders"
id=
"OutboundOrdersResult"
>
<result
property=
"id"
column=
"id"
/>
<result
property=
"id"
column=
"id"
/>
<result
property=
"orderId"
column=
"order_id"
/>
<result
property=
"orderId"
column=
"order_id"
/>
...
@@ -31,40 +31,40 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -31,40 +31,40 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<collection
property=
"outboundOrderItemsList"
ofType=
"OutboundOrderItems"
column=
"id"
select=
"selectOutboundOrderItemsList"
/>
<collection
property=
"outboundOrderItemsList"
ofType=
"OutboundOrderItems"
column=
"id"
select=
"selectOutboundOrderItemsList"
/>
</resultMap>
</resultMap>
<!-- 修复:仅保留子表outbound_order_items的字段映射,删除错误的主表字段 -->
<resultMap
type=
"OutboundOrderItems"
id=
"OutboundOrderItemsResult"
>
<resultMap
type=
"OutboundOrderItems"
id=
"OutboundOrderItemsResult"
>
<result
property=
"id"
column=
"id"
/>
<result
property=
"id"
column=
"id"
/>
<result
property=
"orderId"
column=
"order_id"
/>
<result
property=
"orderId"
column=
"order_id"
/>
<result
property=
"materialId"
column=
"material_id"
/>
<result
property=
"materialId"
column=
"material_id"
/>
<result
property=
"batchId"
column=
"batch_id"
/>
<result
property=
"batchCode"
column=
"batch_code"
/>
<result
property=
"warehouseId"
column=
"warehouse_id"
/>
<result
property=
"warehouseId"
column=
"warehouse_id"
/>
<result
property=
"locationId"
column=
"location_id"
/>
<result
property=
"locationId"
column=
"location_id"
/>
<result
property=
"plannedQuantity"
column=
"planned_quantity"
/>
<result
property=
"plannedQuantity"
column=
"planned_quantity"
/>
<result
property=
"actualQuantity"
column=
"actual_quantity"
/>
<result
property=
"inventoryId"
column=
"inventory_id"
/>
<result
property=
"plannedPackages"
column=
"planned_packages"
/>
<result
property=
"actualQuantity"
column=
"actual_quantity"
/>
<result
property=
"actualPackages"
column=
"actual_packages"
/>
<result
property=
"divisor"
column=
"divisor"
/>
<result
property=
"divisor"
column=
"divisor"
/>
<result
property=
"labelColor"
column=
"label_color"
/>
<result
property=
"labelColor"
column=
"label_color"
/>
<result
property=
"voucherNumber"
column=
"voucher_number"
/>
<result
property=
"voucherNumber"
column=
"voucher_number"
/>
<result
property=
"itemStatus"
column=
"item_status"
/>
<result
property=
"unitPrice"
column=
"unit_price"
/>
<result
property=
"shippedAt"
column=
"shipped_at"
/>
<result
property=
"itemStatus"
column=
"item_status"
/>
<result
property=
"shippedBy"
column=
"shipped_by"
/>
<result
property=
"receivedAt"
column=
"received_at"
/>
<result
property=
"remark"
column=
"remark"
/>
<result
property=
"receivedBy"
column=
"received_by"
/>
<result
property=
"isUsed"
column=
"is_used"
/>
<result
property=
"remark"
column=
"remark"
/>
<result
property=
"sortNo"
column=
"sort_no"
/>
<result
property=
"isUsed"
column=
"is_used"
/>
<result
property=
"createTime"
column=
"create_time"
/>
<result
property=
"sortNo"
column=
"sort_no"
/>
<result
property=
"createUserCode"
column=
"create_user_code"
/>
<result
property=
"createTime"
column=
"create_time"
/>
<result
property=
"updateTime"
column=
"update_time"
/>
<result
property=
"createUserCode"
column=
"create_user_code"
/>
<result
property=
"updateUserCode"
column=
"update_user_code"
/>
<result
property=
"updateTime"
column=
"update_time"
/>
<result
property=
"updateUserCode"
column=
"update_user_code"
/>
</resultMap>
</resultMap>
<sql
id=
"selectOutboundOrdersVo"
>
<sql
id=
"selectOutboundOrdersVo"
>
select id, order_id, system_no, order_type_id, batch_code, warehouse_id, owner_id, order_status, inbound_date, destination, total_planned_quantity, total_actual_quantity, total_packages, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code from outbound_orders
select id, order_id, system_no, order_type_id, batch_code, warehouse_id, owner_id, order_status, inbound_date, destination, total_planned_quantity, total_actual_quantity, total_packages, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code from outbound_orders
</sql>
</sql>
<select
id=
"selectOutboundOrdersList"
parameterType=
"OutboundOrders"
resultMap=
"OutboundOrdersResult"
>
<select
id=
"selectOutboundOrdersList"
parameterType=
"OutboundOrders"
resultMap=
"OutboundOrdersResult"
>
<include
refid=
"selectOutboundOrdersVo"
/>
<include
refid=
"selectOutboundOrdersVo"
/>
<where>
<where>
<if
test=
"orderId != null and orderId != ''"
>
and order_id = #{orderId}
</if>
<if
test=
"orderId != null and orderId != ''"
>
and order_id = #{orderId}
</if>
<if
test=
"systemNo != null and systemNo != ''"
>
and system_no = #{systemNo}
</if>
<if
test=
"systemNo != null and systemNo != ''"
>
and system_no = #{systemNo}
</if>
<if
test=
"orderTypeId != null and orderTypeId != ''"
>
and order_type_id = #{orderTypeId}
</if>
<if
test=
"orderTypeId != null and orderTypeId != ''"
>
and order_type_id = #{orderTypeId}
</if>
...
@@ -83,16 +83,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -83,16 +83,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"updateUserCode != null and updateUserCode != ''"
>
and update_user_code = #{updateUserCode}
</if>
<if
test=
"updateUserCode != null and updateUserCode != ''"
>
and update_user_code = #{updateUserCode}
</if>
</where>
</where>
</select>
</select>
<select
id=
"selectOutboundOrdersById"
parameterType=
"String"
resultMap=
"OutboundOrdersOutboundOrderItemsResult"
>
<select
id=
"selectOutboundOrdersById"
parameterType=
"String"
resultMap=
"OutboundOrdersOutboundOrderItemsResult"
>
select id, order_id, system_no, order_type_id, batch_code, warehouse_id, owner_id, order_status, inbound_date, destination, total_planned_quantity, total_actual_quantity, total_packages, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code
select id, order_id, system_no, order_type_id, batch_code, warehouse_id, owner_id, order_status, inbound_date, destination, total_planned_quantity, total_actual_quantity, total_packages, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code
from outbound_orders
from outbound_orders
where id = #{id}
where id = #{id}
</select>
</select>
<!-- 仅保留子表查询逻辑,字段完整且映射正确 -->
<select
id=
"selectOutboundOrderItemsList"
parameterType=
"String"
resultMap=
"OutboundOrderItemsResult"
>
<select
id=
"selectOutboundOrderItemsList"
parameterType=
"String"
resultMap=
"OutboundOrderItemsResult"
>
select id, order_id, material_id, batch_code, warehouse_id, location_id, planned_quantity, actual_quantity, divisor, label_color, voucher_number, item_status, shipped_at, shipped_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code
select id, order_id, material_id, batch_code, warehouse_id, location_id, planned_quantity, actual_quantity, divisor, label_color, voucher_number, item_status, shipped_at, shipped_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code
, inventory_id
from outbound_order_items
from outbound_order_items
where order_id = #{id}
where order_id = #{id}
</select>
</select>
...
@@ -119,7 +120,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -119,7 +120,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"createUserCode != null"
>
create_user_code,
</if>
<if
test=
"createUserCode != null"
>
create_user_code,
</if>
<if
test=
"updateTime != null"
>
update_time,
</if>
<if
test=
"updateTime != null"
>
update_time,
</if>
<if
test=
"updateUserCode != null"
>
update_user_code,
</if>
<if
test=
"updateUserCode != null"
>
update_user_code,
</if>
</trim>
</trim>
<trim
prefix=
"values ("
suffix=
")"
suffixOverrides=
","
>
<trim
prefix=
"values ("
suffix=
")"
suffixOverrides=
","
>
<if
test=
"id != null"
>
#{id},
</if>
<if
test=
"id != null"
>
#{id},
</if>
<if
test=
"orderId != null"
>
#{orderId},
</if>
<if
test=
"orderId != null"
>
#{orderId},
</if>
...
@@ -141,7 +142,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -141,7 +142,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"createUserCode != null"
>
#{createUserCode},
</if>
<if
test=
"createUserCode != null"
>
#{createUserCode},
</if>
<if
test=
"updateTime != null"
>
#{updateTime},
</if>
<if
test=
"updateTime != null"
>
#{updateTime},
</if>
<if
test=
"updateUserCode != null"
>
#{updateUserCode},
</if>
<if
test=
"updateUserCode != null"
>
#{updateUserCode},
</if>
</trim>
</trim>
</insert>
</insert>
<update
id=
"updateOutboundOrders"
parameterType=
"OutboundOrders"
>
<update
id=
"updateOutboundOrders"
parameterType=
"OutboundOrders"
>
...
@@ -175,14 +176,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -175,14 +176,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</delete>
</delete>
<delete
id=
"deleteOutboundOrdersByIds"
parameterType=
"String"
>
<delete
id=
"deleteOutboundOrdersByIds"
parameterType=
"String"
>
delete from outbound_orders where id in
delete from outbound_orders where id in
<foreach
item=
"id"
collection=
"array"
open=
"("
separator=
","
close=
")"
>
<foreach
item=
"id"
collection=
"array"
open=
"("
separator=
","
close=
")"
>
#{id}
#{id}
</foreach>
</foreach>
</delete>
</delete>
<delete
id=
"deleteOutboundOrderItemsByOrderIds"
parameterType=
"String"
>
<delete
id=
"deleteOutboundOrderItemsByOrderIds"
parameterType=
"String"
>
delete from outbound_order_items where order_id in
delete from outbound_order_items where order_id in
<foreach
item=
"orderId"
collection=
"array"
open=
"("
separator=
","
close=
")"
>
<foreach
item=
"orderId"
collection=
"array"
open=
"("
separator=
","
close=
")"
>
#{orderId}
#{orderId}
</foreach>
</foreach>
...
@@ -193,9 +194,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
...
@@ -193,9 +194,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</delete>
</delete>
<insert
id=
"batchOutboundOrderItems"
>
<insert
id=
"batchOutboundOrderItems"
>
insert into outbound_order_items( id, order_id, material_id, batch_id, warehouse_id, location_id, planned_quantity, actual_quantity, planned_packages, actual_packages, divisor, label_color, voucher_number, unit_price, item_status, received_at, received_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code) values
insert into outbound_order_items(
id, order_id, material_id, batch_code, warehouse_id, location_id,
planned_quantity, actual_quantity, divisor, label_color, voucher_number,
item_status, shipped_at, shipped_by, remark, is_used, sort_no,
create_time, create_user_code, update_time, update_user_code,inventory_id
) values
<foreach
item=
"item"
index=
"index"
collection=
"list"
separator=
","
>
<foreach
item=
"item"
index=
"index"
collection=
"list"
separator=
","
>
( #{item.id}, #{item.orderId}, #{item.materialId}, #{item.batchId}, #{item.warehouseId}, #{item.locationId}, #{item.plannedQuantity}, #{item.actualQuantity}, #{item.plannedPackages}, #{item.actualPackages}, #{item.divisor}, #{item.labelColor}, #{item.voucherNumber}, #{item.unitPrice}, #{item.itemStatus}, #{item.receivedAt}, #{item.receivedBy}, #{item.remark}, #{item.isUsed}, #{item.sortNo}, #{item.createTime}, #{item.createUserCode}, #{item.updateTime}, #{item.updateUserCode})
(
#{item.id}, #{item.orderId}, #{item.materialId}, #{item.batchCode}, #{item.warehouseId},
#{item.locationId}, #{item.plannedQuantity}, #{item.actualQuantity}, #{item.divisor},
#{item.labelColor}, #{item.voucherNumber}, #{item.itemStatus}, #{item.shippedAt},
#{item.shippedBy}, #{item.remark}, #{item.isUsed}, #{item.sortNo}, #{item.createTime},
#{item.createUserCode}, #{item.updateTime}, #{item.updateUserCode},#{item.inventoryId}
)
</foreach>
</foreach>
</insert>
</insert>
</mapper>
</mapper>
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论