单独修改状态接口

This commit is contained in:
2025-07-19 10:49:29 +08:00
parent c2b6e54a09
commit 0ad3f3f3c8
6 changed files with 217 additions and 20 deletions

View File

@@ -42,3 +42,42 @@ export function delStockIo(stockIoId) {
method: 'delete' method: 'delete'
}) })
} }
// 审核出入库单
export function auditStockIo(stockIoId) {
return request({
url: '/wms/stockIo/audit/' + stockIoId,
method: 'post'
})
}
// 撤销出入库单
export function cancelStockIo(stockIoId) {
return request({
url: '/wms/stockIo/cancel/' + stockIoId,
method: 'post'
})
}
// 根据类型和ID查询明细
export function detailByTypeAndId(ioType, stockIoId) {
return request({
url: '/wms/stockIo/detailByTypeAndId',
method: 'get',
params: {
ioType,
stockIoId
}
})
}
// 更新出入库单状态
export function updateStockIoStatus(stockIoId, status) {
return request({
url: '/wms/stockIo/updateStatus/' + stockIoId,
method: 'post',
params: {
status
}
})
}

View File

@@ -191,7 +191,10 @@
append-to-body append-to-body
@close="onDetailClosed" @close="onDetailClosed"
> >
<StockIoDetailPanel :stockIo="detailStockIo" /> <StockIoDetailPanel
:stockIo="detailStockIo"
@status-changed="onStatusChanged"
/>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
@@ -390,6 +393,15 @@ export default {
}, },
onDetailClosed() { onDetailClosed() {
this.getList(); this.getList();
},
onStatusChanged(updatedStockIo) {
// 更新主表中的对应记录状态
const index = this.stockIoList.findIndex(item => item.stockIoId === updatedStockIo.stockIoId);
if (index !== -1) {
this.$set(this.stockIoList, index, updatedStockIo);
}
// 刷新列表
this.getList();
} }
} }
}; };

View File

@@ -63,7 +63,12 @@
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="明细ID" align="center" prop="detailId"/> <el-table-column label="明细ID" align="center" prop="detailId"/>
<el-table-column label="库区/库位ID" align="center" prop="warehouseId" /> <el-table-column label="库区/库位ID" align="center" prop="warehouseId" />
<el-table-column label="源库区/库位ID" align="center" prop="fromWarehouseId" /> <el-table-column
v-if="stockIo.ioType === 'transfer'"
label="源库区/库位ID"
align="center"
prop="fromWarehouseId"
/>
<el-table-column label="物品类型" align="center" prop="itemType" /> <el-table-column label="物品类型" align="center" prop="itemType" />
<el-table-column label="物品ID" align="center" prop="itemId" /> <el-table-column label="物品ID" align="center" prop="itemId" />
<el-table-column label="数量" align="center" prop="quantity" /> <el-table-column label="数量" align="center" prop="quantity" />
@@ -96,29 +101,45 @@
:limit.sync="queryParams.pageSize" :limit.sync="queryParams.pageSize"
@pagination="getList" @pagination="getList"
/> />
<!-- 审核按钮 --> <!-- 操作按钮 -->
<div style="margin-top: 20px; text-align: right;"> <div style="margin-top: 20px; text-align: right;">
<!-- 状态修改按钮 -->
<el-button <el-button
v-if="stockIo.status !== 2" v-if="stockIo.status === 0"
type="warning"
:loading="statusLoading"
@click="handleUpdateStatus"
>{{ getStatusButtonText() }}</el-button>
<!-- 审核按钮 -->
<el-button
v-if="stockIo.status === 1"
type="primary" type="primary"
:loading="auditLoading" :loading="auditLoading"
@click="handleAudit" @click="handleAudit"
>确认入库/审核</el-button> >审核</el-button>
</div> </div>
<!-- 明细编辑弹窗 --> <!-- 明细编辑弹窗 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-form-item label="出入库单ID" prop="stockIoId"> <el-form-item label="出入库单ID" prop="stockIoId">
<el-input v-model="form.stockIoId" placeholder="请输入出入库单ID" :disabled="true" /> <el-input v-model="form.stockIoId" placeholder="请输入出入库单ID" :disabled="true" />
</el-form-item> </el-form-item>
<el-form-item label="库区/库位ID" prop="warehouseId"> <el-form-item label="库区/库位" prop="warehouseId">
<el-input v-model="form.warehouseId" placeholder="请输入库区/库位ID" /> <warehouse-select v-model="form.warehouseId" placeholder="请选择库区/库位" />
</el-form-item> </el-form-item>
<el-form-item label="源库区/库位ID" prop="fromWarehouseId"> <el-form-item
<el-input v-model="form.fromWarehouseId" placeholder="请输入源库区/库位ID" /> v-if="stockIo.ioType === 'transfer'"
label="源库区/库位"
prop="fromWarehouseId"
>
<warehouse-select v-model="form.fromWarehouseId" placeholder="请选择源库区/库位" />
</el-form-item> </el-form-item>
<el-form-item label="物品类型" prop="itemType"> <el-form-item label="物品类型" prop="itemType">
<el-input v-model="form.itemType" placeholder="请输入物品类型" /> <el-select v-model="form.itemType" placeholder="请选择物品类型" style="width: 100%">
<el-option label="原材料" value="raw_material"></el-option>
<el-option label="产品" value="product"></el-option>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="物品ID" prop="itemId"> <el-form-item label="物品ID" prop="itemId">
<el-input v-model="form.itemId" placeholder="请输入物品ID" /> <el-input v-model="form.itemId" placeholder="请输入物品ID" />
@@ -150,9 +171,14 @@
<script> <script>
import { listStockIoDetail, getStockIoDetail, delStockIoDetail, addStockIoDetail, updateStockIoDetail } from "@/api/wms/stockIoDetail"; import { listStockIoDetail, getStockIoDetail, delStockIoDetail, addStockIoDetail, updateStockIoDetail } from "@/api/wms/stockIoDetail";
import { auditStockIo } from "@/api/wms/stockIo"; import { auditStockIo, updateStockIoStatus } from "@/api/wms/stockIo";
import WarehouseSelect from '@/components/WarehouseSelect';
export default { export default {
name: "StockIoDetailPanel", name: "StockIoDetailPanel",
components: {
WarehouseSelect
},
props: { props: {
stockIo: { stockIo: {
type: Object, type: Object,
@@ -176,7 +202,7 @@ export default {
buttonLoading: false, buttonLoading: false,
rules: { rules: {
warehouseId: [ warehouseId: [
{ required: true, message: "库区/库位ID不能为空", trigger: "blur" } { required: true, message: "库区/库位不能为空", trigger: "blur" }
], ],
itemType: [ itemType: [
{ required: true, message: "物品类型不能为空", trigger: "blur" } { required: true, message: "物品类型不能为空", trigger: "blur" }
@@ -193,7 +219,8 @@ export default {
}, },
ids: [], ids: [],
single: true, single: true,
multiple: true multiple: true,
statusLoading: false // 新增状态修改按钮加载状态
}; };
}, },
watch: { watch: {
@@ -225,12 +252,31 @@ export default {
}); });
}, },
handleAudit() { handleAudit() {
this.auditLoading = true; // 检查是否有明细数据
auditStockIo(this.stockIo.stockIoId).then(() => { if (!this.stockIoDetailList || this.stockIoDetailList.length === 0) {
this.$modal.msgSuccess('审核成功'); this.$modal.msgError('请先添加明细数据');
this.$set(this.stockIo, 'status', 2); return;
}).finally(() => { }
this.auditLoading = false;
// 确认审核
this.$modal.confirm('确认要审核此出入库单吗?审核后将影响库存数据。').then(() => {
this.auditLoading = true;
auditStockIo(this.stockIo.stockIoId).then(response => {
this.$modal.msgSuccess('审核成功');
// 更新主表状态
this.$set(this.stockIo, 'status', 2);
// 刷新明细列表
this.getList();
// 通知父组件状态已更新
this.$emit('status-changed', this.stockIo);
}).catch(error => {
console.error('审核失败:', error);
this.$modal.msgError('审核失败:' + (error.message || '未知错误'));
}).finally(() => {
this.auditLoading = false;
});
}).catch(() => {
// 用户取消审核
}); });
}, },
handleSelectionChange(selection) { handleSelectionChange(selection) {
@@ -256,6 +302,15 @@ export default {
}); });
}, },
submitForm() { submitForm() {
// 动态添加源库位验证规则
if (this.stockIo.ioType === 'transfer') {
this.$set(this.rules, 'fromWarehouseId', [
{ required: true, message: "源库区/库位不能为空", trigger: "blur" }
]);
} else {
this.$delete(this.rules, 'fromWarehouseId');
}
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
this.buttonLoading = true; this.buttonLoading = true;
@@ -316,6 +371,53 @@ export default {
this.download('klp/stockIoDetail/export', { this.download('klp/stockIoDetail/export', {
...this.queryParams ...this.queryParams
}, `stockIoDetail_${new Date().getTime()}.xlsx`) }, `stockIoDetail_${new Date().getTime()}.xlsx`)
},
getAuditButtonText() {
if (this.stockIo.ioType === 'in') {
return '确认入库/审核';
} else if (this.stockIo.ioType === 'out') {
return '确认出库/审核';
} else if (this.stockIo.ioType === 'transfer') {
return '确认移库/审核';
} else {
return '审核';
}
},
getStatusButtonText() {
if (this.stockIo.ioType === 'in') {
return '确认入库';
} else if (this.stockIo.ioType === 'out') {
return '确认出库';
} else if (this.stockIo.ioType === 'transfer') {
return '确认移库';
} else {
return '修改状态';
}
},
handleUpdateStatus() {
// 检查是否有明细数据
if (!this.stockIoDetailList || this.stockIoDetailList.length === 0) {
this.$modal.msgError('请先添加明细数据');
return;
}
this.$modal.confirm('确认要提交此出入库单吗?提交后将无法修改明细。').then(() => {
this.statusLoading = true;
updateStockIoStatus(this.stockIo.stockIoId, 1).then(response => {
this.$modal.msgSuccess('状态更新成功');
// 更新主表状态
this.$set(this.stockIo, 'status', 1);
// 通知父组件状态已更新
this.$emit('status-changed', this.stockIo);
}).catch(error => {
console.error('状态更新失败:', error);
this.$modal.msgError('状态更新失败:' + (error.message || '未知错误'));
}).finally(() => {
this.statusLoading = false;
});
}).catch(() => {
// 用户取消状态更新
});
} }
} }
} }

View File

@@ -126,4 +126,14 @@ public class WmsStockIoController extends BaseController {
public R<List<WmsStockIoDetailVo>> detailByTypeAndId(@RequestParam String ioType, @RequestParam Long stockIoId) { public R<List<WmsStockIoDetailVo>> detailByTypeAndId(@RequestParam String ioType, @RequestParam Long stockIoId) {
return R.ok(iWmsStockIoService.detailByTypeAndId(ioType, stockIoId)); return R.ok(iWmsStockIoService.detailByTypeAndId(ioType, stockIoId));
} }
/**
* 更新出入库单状态
*/
@Log(title = "出入库单主", businessType = BusinessType.UPDATE)
@PostMapping("/updateStatus/{stockIoId}")
public R<Void> updateStatus(@NotNull(message = "主键不能为空") @PathVariable Long stockIoId,
@RequestParam Integer status) {
return toAjax(iWmsStockIoService.updateStatus(stockIoId, status));
}
} }

View File

@@ -62,4 +62,9 @@ public interface IWmsStockIoService {
* 根据ioType和stockIoId联查明细 * 根据ioType和stockIoId联查明细
*/ */
java.util.List<WmsStockIoDetailVo> detailByTypeAndId(String ioType, Long stockIoId); java.util.List<WmsStockIoDetailVo> detailByTypeAndId(String ioType, Long stockIoId);
/**
* 更新出入库单状态
*/
Boolean updateStatus(Long stockIoId, Integer status);
} }

View File

@@ -238,6 +238,35 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService {
return voList; return voList;
} }
/**
* 更新出入库单状态
*/
@Override
public Boolean updateStatus(Long stockIoId, Integer status) {
WmsStockIo stockIo = baseMapper.selectById(stockIoId);
if (stockIo == null) {
throw new ServiceException("单据不存在");
}
// 状态流转验证
if (stockIo.getStatus() == 0 && status == 1) {
// 草稿 -> 已提交:需要检查是否有明细
List<WmsStockIoDetail> details = stockIoDetailMapper.selectList(
Wrappers.<WmsStockIoDetail>lambdaQuery().eq(WmsStockIoDetail::getStockIoId, stockIoId)
);
if (details == null || details.isEmpty()) {
throw new ServiceException("单据明细不能为空,无法提交");
}
} else if (stockIo.getStatus() == 1 && status == 0) {
// 已提交 -> 草稿:允许回退
} else {
throw new ServiceException("状态流转不允许");
}
stockIo.setStatus(status);
return baseMapper.updateById(stockIo) > 0;
}
/** /**
* 库存增减isAdd=true为增加false为减少减少时校验库存是否足够 * 库存增减isAdd=true为增加false为减少减少时校验库存是否足够
*/ */