fix(biz): 修复入库退料相关功能
This commit is contained in:
parent
9835388514
commit
8c0e19372c
@ -30,7 +30,7 @@ public class RawStorageRespVO {
|
||||
|
||||
@Schema(description = "业务类型 (10 采购入库,11 盘盈入库,12 其它入库 21 生产领料 22 盘亏出库 23采购退料)", example = "1")
|
||||
@ExcelProperty("业务类型 (10 采购入库,11 盘盈入库,12 其它入库 21 生产领料 22 盘亏出库 23采购退料)")
|
||||
private Integer businessType;
|
||||
private String businessType;
|
||||
|
||||
@Schema(description = "备注", example = "随便")
|
||||
@ExcelProperty("备注")
|
||||
|
||||
@ -82,4 +82,6 @@ public class RawStorageMatPageReqVO extends PageParam {
|
||||
@Schema(description = "存货账单号")
|
||||
private String inventBillNo;
|
||||
|
||||
private String billNo;
|
||||
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ public class RawStorageDO extends BaseDO {
|
||||
/**
|
||||
* 业务类型 (10 采购入库,11 盘盈入库,12 其它入库 21 生产领料 22 盘亏出库 23采购退料)
|
||||
*/
|
||||
private Integer businessType;
|
||||
private String businessType;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
|
||||
@ -109,4 +109,6 @@ public class RawStorageMatDO extends BaseDO {
|
||||
*/
|
||||
private String inventBillNo;
|
||||
|
||||
private BigDecimal returnQty;
|
||||
|
||||
}
|
||||
|
||||
@ -22,11 +22,10 @@ public interface RawStorageMapper extends BaseMapperX<RawStorageDO> {
|
||||
.eqIfPresent(RawStorageDO::getBusinessType, reqVO.getBusinessType())
|
||||
.eqIfPresent(RawStorageDO::getRemark, reqVO.getRemark())
|
||||
.eqIfPresent(RawStorageDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(RawStorageDO::getCreateTime, reqVO.getCreateTime())
|
||||
.eqIfPresent(RawStorageDO::getSupplierNo, reqVO.getSupplierNo())
|
||||
.likeIfPresent(RawStorageDO::getSupplierName, reqVO.getSupplierName())
|
||||
.eqIfPresent(RawStorageDO::getSupplierId, reqVO.getSupplierId())
|
||||
// .betweenIfPresent(RawStorageDO::getBillDate, reqVO.getBillDate())
|
||||
.betweenIfPresent(RawStorageDO::getBillDate, reqVO.getBillDate())
|
||||
.eqIfPresent(RawStorageDO::getOperatorId, reqVO.getOperatorId())
|
||||
.likeIfPresent(RawStorageDO::getOperatorName, reqVO.getOperatorName())
|
||||
.eqIfPresent(RawStorageDO::getRelarionNo, reqVO.getRelarionNo())
|
||||
|
||||
@ -39,11 +39,12 @@ public interface RawStorageInventoryMapper extends BaseMapperX<RawStorageInvento
|
||||
return inventoryDO != null ? inventoryDO.getInventBillNo() : null;
|
||||
}
|
||||
|
||||
default RawStorageInventoryDO selectByMatCodeAndBatchNo(String matCode, String spec, Integer storeHouseId, Integer storeAreaId) {
|
||||
default RawStorageInventoryDO selectByMatCodeAndBatchNo(String matCode, String spec, Integer storeHouseId, Integer storeAreaId, String lotNo) {
|
||||
return selectOne(new LambdaQueryWrapperX<RawStorageInventoryDO>()
|
||||
.eq(RawStorageInventoryDO::getMatCode, matCode)
|
||||
.eq(RawStorageInventoryDO::getSpec, spec)
|
||||
.eq(RawStorageInventoryDO::getStoreHouseId, storeHouseId)
|
||||
.eq(RawStorageInventoryDO::getStoreAreaId, storeAreaId));
|
||||
.eq(RawStorageInventoryDO::getStoreAreaId, storeAreaId)
|
||||
.eqIfPresent(RawStorageInventoryDO::getLotNo, lotNo)
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ import com.ningxia.yunxi.chemmes.module.biz.service.rawstoragelog.RawStorageLogS
|
||||
import com.ningxia.yunxi.chemmes.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.ningxia.yunxi.chemmes.module.system.service.user.AdminUserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -81,16 +82,35 @@ public class RawStorageServiceImpl implements RawStorageService {
|
||||
}
|
||||
|
||||
if (createReqVO.getStatus().equals("2")) {
|
||||
saveStorageLog(rawStorage);
|
||||
}
|
||||
|
||||
// 返回
|
||||
return rawStorage.getId();
|
||||
}
|
||||
|
||||
private void saveStorageLog(RawStorageDO rawStorage) {
|
||||
List<RawStorageMatDO> rawStorageMatDOS = rawStorageMatMapper.selectListByStockId(rawStorage.getId());
|
||||
// 保存入库单
|
||||
// 物料编码 和 批次号 存在,则更新
|
||||
String dpstNo = rawStorageLogService.generateOrderNo(rawStorage.getOperatorType());
|
||||
for (RawStorageMatDO rawStorageMatDO : rawStorageMatDOS) {
|
||||
RawStorageInventoryDO rawStorageInventoryDO = rawStorageInventoryService.selectByMatCodeAndBatchNo(rawStorageMatDO);
|
||||
if (rawStorageInventoryDO != null) {
|
||||
rawStorageInventoryDO.setYardQty(rawStorageInventoryDO.getYardQty().add(rawStorageMatDO.getPurQty()));
|
||||
rawStorageInventoryDO.setUseQty(rawStorageInventoryDO.getUseQty().add(rawStorageMatDO.getPurQty()));
|
||||
rawStorageInventoryDO.setYardQty(rawStorageInventoryDO.getYardQty().add(rawStorageMatDO.getOperatorQty()));
|
||||
rawStorageInventoryDO.setUseQty(rawStorageInventoryDO.getUseQty().add(rawStorageMatDO.getOperatorQty()));
|
||||
rawStorageInventoryService.updateRawStorageInventory(rawStorageInventoryDO);
|
||||
} else {
|
||||
rawStorageInventoryDO = getRawStorageInventoryDO(rawStorageMatDO);
|
||||
}
|
||||
rawStorageMatDO.setInventBillNo(rawStorageInventoryDO.getInventBillNo());
|
||||
rawStorageMatMapper.updateById(rawStorageMatDO);
|
||||
saveStorageLog(rawStorage, rawStorageMatDO, dpstNo, rawStorageInventoryDO);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private RawStorageInventoryDO getRawStorageInventoryDO(RawStorageMatDO rawStorageMatDO) {
|
||||
RawStorageInventoryDO rawStorageInventoryDO;
|
||||
rawStorageInventoryDO = new RawStorageInventoryDO();
|
||||
rawStorageInventoryDO.setStoreHouseId(rawStorageMatDO.getStoreHouseId());
|
||||
rawStorageInventoryDO.setStoreAreaId(rawStorageMatDO.getStoreAreaId());
|
||||
@ -105,8 +125,8 @@ public class RawStorageServiceImpl implements RawStorageService {
|
||||
rawStorageInventoryDO.setUnit(rawStorageMatDO.getUnit());
|
||||
rawStorageInventoryDO.setLotNo(rawStorageMatDO.getLotNo());
|
||||
rawStorageInventoryDO.setDescription(rawStorageMatDO.getDescription());
|
||||
rawStorageInventoryDO.setYardQty(rawStorageMatDO.getPurQty());
|
||||
rawStorageInventoryDO.setUseQty(rawStorageMatDO.getPurQty());
|
||||
rawStorageInventoryDO.setYardQty(rawStorageMatDO.getOperatorQty());
|
||||
rawStorageInventoryDO.setUseQty(rawStorageMatDO.getOperatorQty());
|
||||
rawStorageInventoryDO.setPreQty(BigDecimal.ZERO);
|
||||
// rawStorageInventoryDO.setPrice(rawStorageMatDO.getPrice());
|
||||
// rawStorageInventoryDO.setPackQty(rawStorageMatDO.getPackQty());
|
||||
@ -115,15 +135,45 @@ public class RawStorageServiceImpl implements RawStorageService {
|
||||
rawStorageInventoryDO.setInventBillNo(rawStorageInventoryService.getBillNo());
|
||||
|
||||
rawStorageInventoryService.saveRawStorageInventory(rawStorageInventoryDO);
|
||||
return rawStorageInventoryDO;
|
||||
}
|
||||
|
||||
}
|
||||
rawStorageLogService.saveRawStorageLog(null);
|
||||
|
||||
}
|
||||
|
||||
// 返回
|
||||
return rawStorage.getId();
|
||||
private void saveStorageLog(RawStorageDO rawStorage, RawStorageMatDO rawStorageMatDO, String dpstNo, RawStorageInventoryDO rawStorageInventoryDO) {
|
||||
RawStorageLogDO rawStorageLogDO = new RawStorageLogDO();
|
||||
// rawStorageLogDO.setStockId();
|
||||
// rawStorageLogDO.setDescription();
|
||||
rawStorageLogDO.setStatus("1");
|
||||
rawStorageLogDO.setStoreHouseId(rawStorageMatDO.getStoreHouseId());
|
||||
rawStorageLogDO.setStoreAreaId(rawStorageMatDO.getStoreAreaId());
|
||||
rawStorageLogDO.setStoreHouseCd(rawStorageMatDO.getStoreHouseCd());
|
||||
rawStorageLogDO.setStoreHouseName(rawStorageMatDO.getStoreHouseName());
|
||||
rawStorageLogDO.setStoreAreCd(rawStorageMatDO.getStoreAreCd());
|
||||
rawStorageLogDO.setStoreAreaName(rawStorageMatDO.getStoreAreaName());
|
||||
rawStorageLogDO.setMaterialId(rawStorageMatDO.getMaterialId());
|
||||
rawStorageLogDO.setMatName(rawStorageMatDO.getMatName());
|
||||
rawStorageLogDO.setMatCode(rawStorageMatDO.getMatCode());
|
||||
rawStorageLogDO.setSpec(rawStorageMatDO.getSpec());
|
||||
rawStorageLogDO.setUnit(rawStorageMatDO.getUnit());
|
||||
rawStorageLogDO.setLotNo(rawStorageMatDO.getLotNo());
|
||||
rawStorageLogDO.setOperatorQty(rawStorageMatDO.getOperatorQty());
|
||||
rawStorageLogDO.setOperatorType("1");
|
||||
rawStorageLogDO.setBusinessType(rawStorage.getBusinessType());
|
||||
// rawStorageLogDO.setStorageAft();
|
||||
// rawStorageLogDO.setStorageBef();
|
||||
// rawStorageLogDO.setStockItemId(rawStorageMatDO.getId());
|
||||
rawStorageLogDO.setDpstNo(dpstNo);
|
||||
rawStorageLogDO.setSupplierNo(rawStorage.getSupplierNo());
|
||||
rawStorageLogDO.setSupplierName(rawStorage.getSupplierName());
|
||||
rawStorageLogDO.setSupplierId(rawStorage.getSupplierId());
|
||||
rawStorageLogDO.setOperatorQty(rawStorageMatDO.getOperatorQty());
|
||||
rawStorageLogDO.setBillDate(LocalDate.now());
|
||||
rawStorageLogDO.setOperatorId(rawStorage.getOperatorId());
|
||||
rawStorageLogDO.setOperatorName(rawStorage.getOperatorName());
|
||||
rawStorageLogDO.setRelarionNo(rawStorage.getBillNo());
|
||||
rawStorageLogDO.setRelarionId(rawStorage.getId());
|
||||
rawStorageLogDO.setRelarionDetailId(rawStorageMatDO.getId());
|
||||
rawStorageLogDO.setInventBillNo(rawStorageInventoryDO.getInventBillNo());
|
||||
rawStorageLogService.saveRawStorageLog(rawStorageLogDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -149,10 +199,14 @@ public class RawStorageServiceImpl implements RawStorageService {
|
||||
for (RawStorageMatSaveReqVO matVO : updateReqVO.getItems()) {
|
||||
RawStorageMatDO mat = BeanUtils.toBean(matVO, RawStorageMatDO.class);
|
||||
mat.setStockId(updateReqVO.getId());
|
||||
mat.setId(null);
|
||||
rawStorageMatMapper.insert(mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ("2".equals(updateReqVO.getStatus())) {
|
||||
saveStorageLog(updateObj);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -101,6 +101,6 @@ public class RawStorageInventoryServiceImpl implements RawStorageInventoryServic
|
||||
@Override
|
||||
public RawStorageInventoryDO selectByMatCodeAndBatchNo(RawStorageMatDO rawStorageMatDO) {
|
||||
return rawStorageInventoryMapper.selectByMatCodeAndBatchNo(rawStorageMatDO.getMatCode(),
|
||||
rawStorageMatDO.getSpec(), rawStorageMatDO.getStoreHouseId(), rawStorageMatDO.getStoreAreaId());
|
||||
rawStorageMatDO.getSpec(), rawStorageMatDO.getStoreHouseId(), rawStorageMatDO.getStoreAreaId(), rawStorageMatDO.getLotNo());
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +56,8 @@ declare module 'vue' {
|
||||
ElOption: typeof import('element-plus/es')['ElOption']
|
||||
ElPagination: typeof import('element-plus/es')['ElPagination']
|
||||
ElPopover: typeof import('element-plus/es')['ElPopover']
|
||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
||||
ElRow: typeof import('element-plus/es')['ElRow']
|
||||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||
@ -68,6 +70,7 @@ declare module 'vue' {
|
||||
ElTag: typeof import('element-plus/es')['ElTag']
|
||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
|
||||
ElUpload: typeof import('element-plus/es')['ElUpload']
|
||||
Error: typeof import('./../components/Error/src/Error.vue')['default']
|
||||
FlowCondition: typeof import('./../components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue')['default']
|
||||
Form: typeof import('./../components/Form/src/Form.vue')['default']
|
||||
@ -88,6 +91,7 @@ declare module 'vue' {
|
||||
PropertiesPanel: typeof import('./../components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue')['default']
|
||||
Qrcode: typeof import('./../components/Qrcode/src/Qrcode.vue')['default']
|
||||
ReceiveTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue')['default']
|
||||
Returnstorage: typeof import('./../api/biz/returnstorage/index.ts')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterSearch: typeof import('./../components/RouterSearch/index.vue')['default']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
@ -96,6 +100,7 @@ declare module 'vue' {
|
||||
ShortcutDateRangePicker: typeof import('./../components/ShortcutDateRangePicker/index.vue')['default']
|
||||
SignalAndMessage: typeof import('./../components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue')['default']
|
||||
Sticky: typeof import('./../components/Sticky/src/Sticky.vue')['default']
|
||||
StorageSelectDialog: typeof import('./../views/biz/returnstorage/StorageSelectDialog.vue')['default']
|
||||
SummaryCard: typeof import('./../components/SummaryCard/index.vue')['default']
|
||||
Table: typeof import('./../components/Table/src/Table.vue')['default']
|
||||
Tooltip: typeof import('./../components/Tooltip/src/Tooltip.vue')['default']
|
||||
@ -109,6 +114,7 @@ declare module 'vue' {
|
||||
VerifyPoints: typeof import('./../components/Verifition/src/Verify/VerifyPoints.vue')['default']
|
||||
VerifySlide: typeof import('./../components/Verifition/src/Verify/VerifySlide.vue')['default']
|
||||
VerticalButtonGroup: typeof import('./../components/VerticalButtonGroup/index.vue')['default']
|
||||
'Workspace.xml': typeof import('./../../.idea/workspace.xml.tmp')['default']
|
||||
XButton: typeof import('./../components/XButton/src/XButton.vue')['default']
|
||||
XTextButton: typeof import('./../components/XButton/src/XTextButton.vue')['default']
|
||||
}
|
||||
|
||||
@ -20,13 +20,9 @@
|
||||
:disabled="formType === 'detail'"
|
||||
class="!w-full"
|
||||
>
|
||||
<el-option label="采购入库" value="10" />
|
||||
<el-option label="盘盈入库" value="11" />
|
||||
<el-option label="其它入库" value="12" />
|
||||
<el-option label="生产领料" value="21" />
|
||||
<el-option label="盘亏出库" value="22" />
|
||||
<el-option label="采购退料" value="23" />
|
||||
<el-option label="其它退料" value="24" />
|
||||
<el-option label="盘盈入库" value="11" />
|
||||
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -80,10 +76,10 @@
|
||||
|
||||
<!-- 明细信息 -->
|
||||
<div>
|
||||
<div style="font-weight: bold; margin-bottom: 15px; display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="font-weight: bold; margin-bottom: 15px; display: flex; align-items: center;">
|
||||
<span>明细信息</span>
|
||||
<el-button type="primary" @click="openMaterialSelect" v-if="formType !== 'detail'">
|
||||
<Icon icon="ep:plus" class="mr-1" /> 选择物料
|
||||
<Icon icon="ep:plus" class="mr-5px" />新增
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
@ -110,18 +106,19 @@
|
||||
<span>{{ scope.row.spec || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="入库数量 (*)" min-width="100px" align="center">
|
||||
<template #default="scope">
|
||||
<el-table-column label="入库数量 (*)" min-width="120px" align="center" >
|
||||
<template #default="scope" >
|
||||
<MoneyInput
|
||||
v-model="scope.row.operatorQty"
|
||||
:decimal-places="2"
|
||||
:allow-negative="false"
|
||||
:show-prefix="false"
|
||||
placeholder="请输入"
|
||||
:disabled="formType === 'detail'"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="仓储名称 (*)" min-width="120px" align="center">
|
||||
<el-table-column label="仓储名称 (*)" min-width="150px" align="center">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.storeHouseId"
|
||||
@ -139,7 +136,7 @@
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库区名称 (*)" min-width="120px" align="center">
|
||||
<el-table-column label="库区名称 (*)" min-width="150px" align="center">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.storeAreaId"
|
||||
@ -161,17 +158,6 @@
|
||||
<template #default="scope">
|
||||
<el-input
|
||||
v-model="scope.row.lotNo"
|
||||
placeholder="手动输入"
|
||||
:disabled="formType === 'detail'"
|
||||
class="!w-full"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<el-input
|
||||
v-model="scope.row.description"
|
||||
placeholder="请输入"
|
||||
:disabled="formType === 'detail'"
|
||||
class="!w-full"
|
||||
/>
|
||||
@ -182,7 +168,7 @@
|
||||
<span>{{ getUnitName(scope.row.unit) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="80px" align="center">
|
||||
<el-table-column label="操作" min-width="70px" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
@ -223,7 +209,6 @@
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import Dialog from '@/components/Dialog/src/Dialog.vue'
|
||||
import * as RawStorageApi from '@/api/biz/rawstorage'
|
||||
import * as RawStorageMatApi from '@/api/biz/rawstoragemat'
|
||||
import * as WarehouseApi from '@/api/biz/storehouse'
|
||||
import * as AreaApi from '@/api/biz/storearea'
|
||||
import { getUnitName } from '@/utils/dict'
|
||||
@ -240,9 +225,8 @@ const formLoading = ref(false)
|
||||
const formType = ref('')
|
||||
const formRef = ref()
|
||||
|
||||
// 仓储和库区选项
|
||||
// 仓储选项
|
||||
const warehouseOptions = ref([])
|
||||
const areaOptions = ref([])
|
||||
|
||||
const formData = reactive({
|
||||
id: undefined,
|
||||
@ -280,9 +264,8 @@ const open = async (type: string, id?: number) => {
|
||||
formType.value = type
|
||||
resetForm()
|
||||
|
||||
// 加载仓储和库区数据
|
||||
// 加载仓储数据
|
||||
await loadWarehouseList()
|
||||
await loadAreaList()
|
||||
|
||||
if (id) {
|
||||
// 修改或详情时加载数据
|
||||
@ -291,9 +274,29 @@ const open = async (type: string, id?: number) => {
|
||||
const data = await RawStorageApi.getRawStorage(id)
|
||||
Object.assign(formData, data)
|
||||
// 加载明细数据
|
||||
const params = { stockId: id }
|
||||
const matData = await RawStorageMatApi.getRawStorageMatPage(params)
|
||||
detailList.value = matData.list || []
|
||||
detailList.value = data.items || []
|
||||
// 为每条明细加载对应的库区选项
|
||||
for (const item of detailList.value) {
|
||||
// 根据仓储ID加载库区下拉框
|
||||
if (item.storeHouseId) {
|
||||
console.log('正在加载库区列表,storeHouseId:', item.storeHouseId)
|
||||
try {
|
||||
const list = await AreaApi.getStoreAreaSelect(item.storeHouseId)
|
||||
console.log('库区列表加载成功:', list)
|
||||
// 确保库区选项的id是数字类型
|
||||
item.areaOptions = (list || []).map((area: any) => ({
|
||||
...area,
|
||||
id: Number(area.id)
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('加载库区列表失败:', error)
|
||||
item.areaOptions = []
|
||||
}
|
||||
} else {
|
||||
console.log('storeHouseId为空,不加载库区列表')
|
||||
item.areaOptions = []
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
@ -305,23 +308,16 @@ defineExpose({ open })
|
||||
const loadWarehouseList = async () => {
|
||||
try {
|
||||
const list = await WarehouseApi.getStoreHouseSelect("1")
|
||||
warehouseOptions.value = list || []
|
||||
// 确保仓储选项的id是数字类型
|
||||
warehouseOptions.value = (list || []).map((item: any) => ({
|
||||
...item,
|
||||
id: Number(item.id)
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('加载仓储列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/** 加载库区列表 */
|
||||
const loadAreaList = async (storeHouseId?: number) => {
|
||||
try {
|
||||
if (!storeHouseId) return
|
||||
const list = await AreaApi.getStoreAreaSelect(storeHouseId)
|
||||
areaOptions.value = list || []
|
||||
} catch (error) {
|
||||
console.error('加载库区列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/** 打开物料选择弹窗 */
|
||||
const openMaterialSelect = () => {
|
||||
materialSelectRef.value.open()
|
||||
@ -381,7 +377,11 @@ const handleWarehouseChange = async (row: any) => {
|
||||
|
||||
try {
|
||||
const list = await AreaApi.getStoreAreaSelect(row.storeHouseId)
|
||||
row.areaOptions = list || []
|
||||
// 确保库区选项的id是数字类型
|
||||
row.areaOptions = (list || []).map((area: any) => ({
|
||||
...area,
|
||||
id: Number(area.id)
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('加载库区列表失败:', error)
|
||||
row.areaOptions = []
|
||||
@ -543,6 +543,5 @@ const resetForm = () => {
|
||||
/** 初始化 */
|
||||
onMounted(() => {
|
||||
loadWarehouseList()
|
||||
loadAreaList()
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -56,7 +56,7 @@
|
||||
<ContentWrap class="!p-10px">
|
||||
<div style="display: flex; flex-direction: column; height: calc(50vh - 180px);">
|
||||
<div style="flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden;">
|
||||
<div style="font-weight: bold; margin-bottom: 8px;">退料单信息</div>
|
||||
<div style="font-weight: bold; margin-bottom: 8px;">入库单信息</div>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
@ -76,7 +76,7 @@
|
||||
<span v-else-if="scope.row.businessType === '12'">其它入库</span>
|
||||
<span v-else-if="scope.row.businessType === '21'">生产领料</span>
|
||||
<span v-else-if="scope.row.businessType === '22'">盘亏出库</span>
|
||||
<span v-else-if="scope.row.businessType === '23'">采购退料</span>
|
||||
<span v-else-if="scope.row.businessType === '23'">标准采购退料</span>
|
||||
<span v-else-if="scope.row.businessType === '24'">其它退料</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
@ -135,7 +135,7 @@
|
||||
|
||||
<!-- 退料明细信息表格(子表) -->
|
||||
<ContentWrap class="!p-15px" style="height: calc(50vh - 60px);">
|
||||
<div style="font-weight: bold; margin-bottom: 8px;">退料明细信息</div>
|
||||
<div style="font-weight: bold; margin-bottom: 8px;">入库明细信息</div>
|
||||
<div style="height: calc(100% - 40px); overflow: auto;">
|
||||
<el-table
|
||||
v-loading="detailLoading"
|
||||
@ -151,7 +151,7 @@
|
||||
<el-table-column label="物料编码" align="center" prop="matCode" />
|
||||
<el-table-column label="物料名称" align="center" prop="matName" />
|
||||
<el-table-column label="规格型号" align="center" prop="spec" />
|
||||
<el-table-column label="入库数量" align="center" prop="sourceQty" />
|
||||
<el-table-column label="入库数量" align="center" prop="operatorQty" />
|
||||
<el-table-column label="批次号" align="center" prop="lotNo" />
|
||||
<el-table-column label="仓储名称" align="center" prop="storeHouseName" />
|
||||
<el-table-column label="库区名称" align="center" prop="storeAreaName" />
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible" width="800px">
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible" width="70%">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
@ -7,104 +7,285 @@
|
||||
label-width="110px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="单据编号" prop="billNo">
|
||||
<el-input v-model="formData.billNo" placeholder="请输入单据编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="操作类型 1为入库,2为出库" prop="operatorType">
|
||||
<el-radio-group v-model="formData.operatorType">
|
||||
<el-radio label="1">请选择字典生成</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="业务类型 (10 采购入库,11 盘盈入库,12 其它入库 21 生产领料 22 盘亏出库 23采购退料)" prop="businessType">
|
||||
<el-select v-model="formData.businessType" placeholder="请选择业务类型 (10 采购入库,11 盘盈入库,12 其它入库 21 生产领料 22 盘亏出库 23采购退料)">
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
<!-- 基本信息 -->
|
||||
<div class="mb-6">
|
||||
<div style="font-weight: bold; margin-bottom: 15px;">基本信息</div>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="业务类型" prop="businessType">
|
||||
<el-select
|
||||
v-model="formData.businessType"
|
||||
placeholder="请选择"
|
||||
:disabled="formType === 'detail'"
|
||||
class="!w-full"
|
||||
>
|
||||
<el-option label="标准采购退料" value="3" />
|
||||
<el-option label="设备采购退料" value="4" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="formData.remark" placeholder="请输入备注" />
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="退料单号" prop="billNo">
|
||||
<el-input
|
||||
v-model="formData.billNo"
|
||||
placeholder="保存时自动生成"
|
||||
disabled
|
||||
class="!w-full"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态:1 已创建;2 提交" prop="status">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio label="1">请选择字典生成</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="供应商编码" prop="supplierNo">
|
||||
<el-input v-model="formData.supplierNo" placeholder="请输入供应商编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="供应商名称" prop="supplierName">
|
||||
<el-input v-model="formData.supplierName" placeholder="请输入供应商名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="供应商id" prop="supplierId">
|
||||
<el-input v-model="formData.supplierId" placeholder="请输入供应商id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="业务日期" prop="billDate">
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="退料日期" prop="billDate">
|
||||
<el-date-picker
|
||||
v-model="formData.billDate"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择业务日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="请选择日期"
|
||||
:disabled="formType === 'detail'"
|
||||
class="!w-full"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作人id" prop="operatorId">
|
||||
<el-input v-model="formData.operatorId" placeholder="请输入操作人id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="操作人" prop="operatorName">
|
||||
<el-input v-model="formData.operatorName" placeholder="请输入操作人" />
|
||||
</el-form-item>
|
||||
<el-form-item label="关联单号" prop="relarionNo">
|
||||
<el-input v-model="formData.relarionNo" placeholder="请输入关联单号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="关联单号id" prop="relarionId">
|
||||
<el-input v-model="formData.relarionId" placeholder="请输入关联单号id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单据类型(1 标准采购申请 2设备采购申请 3 标准采购退料 4设备采购退料)" prop="billType">
|
||||
<el-select v-model="formData.billType" placeholder="请选择单据类型(1 标准采购申请 2设备采购申请 3 标准采购退料 4设备采购退料)">
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="单据状态" prop="status">
|
||||
<el-select v-model="formData.status" disabled class="!w-full">
|
||||
<el-option label="已创建" value="1" />
|
||||
<el-option label="已提交" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="来源单号" prop="sourceNo">
|
||||
<el-input v-model="formData.sourceNo" placeholder="请输入来源单号" />
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="供应商" prop="supplierName">
|
||||
<el-select
|
||||
v-model="formData.supplierName"
|
||||
placeholder="请选择"
|
||||
:disabled="formType === 'detail'"
|
||||
class="!w-full"
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in supplierOptions"
|
||||
:key="item.id"
|
||||
:label="item.supplierName"
|
||||
:value="item.supplierName"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="来源单号id" prop="sourceId">
|
||||
<el-input v-model="formData.sourceId" placeholder="请输入来源单号id" />
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="采购入库单" prop="relarionNo">
|
||||
<el-input
|
||||
v-model="formData.relarionNo"
|
||||
placeholder="点击选择入库单"
|
||||
:disabled="formType === 'detail'"
|
||||
class="!w-full"
|
||||
@click="openStorageSelect"
|
||||
readonly
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
placeholder="请输入"
|
||||
:disabled="formType === 'detail'"
|
||||
class="!w-full"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 明细信息 -->
|
||||
<div>
|
||||
<div style="font-weight: bold; margin-bottom: 15px; display: flex; align-items: center;">
|
||||
<el-button type="primary" @click="openMaterialSelect" v-if="formType !== 'detail'">
|
||||
<Icon icon="ep:plus" class="mr-1" /> 选择物料
|
||||
</el-button>
|
||||
<span style="margin-left: 10px;">明细信息</span>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="detailList"
|
||||
:stripe="true"
|
||||
:show-overflow-tooltip="true"
|
||||
border
|
||||
style="width: 100%;"
|
||||
>
|
||||
<el-table-column label="序号" type="index" min-width="60px" align="center" />
|
||||
<el-table-column label="物料编码" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.matCode || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="物料名称" min-width="150px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.matName || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格型号" min-width="100px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.spec || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="收货数量" min-width="100px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.sourceQty || '0' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已退料数量" min-width="100px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.returnedQty || '0' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="*退料数量" min-width="120px" align="center" >
|
||||
<template #default="scope" >
|
||||
<MoneyInput
|
||||
v-model="scope.row.returnQty"
|
||||
:decimal-places="2"
|
||||
:allow-negative="false"
|
||||
:show-prefix="false"
|
||||
placeholder="手动输入"
|
||||
:disabled="formType === 'detail'"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="批次号" min-width="100px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.lotNo || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="仓储名称" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.storeHouseName || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库区名称" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.storeAreaName || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="入库日期" min-width="110px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.inDate || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" min-width="80px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ getUnitName(scope.row.unit) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="存货账单号" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.inventBillNo || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="80px" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="formType !== 'detail'"
|
||||
type="danger"
|
||||
link
|
||||
@click="handleDeleteDetail(scope.$index)"
|
||||
>
|
||||
<Icon icon="ep:delete" class="mr-1" /> 删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button
|
||||
v-if="formType !== 'detail'"
|
||||
type="primary"
|
||||
@click="handleSubmit('save')"
|
||||
:loading="formLoading"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="formType !== 'detail'"
|
||||
type="primary"
|
||||
@click="handleSubmit('confirm')"
|
||||
:loading="formLoading"
|
||||
>
|
||||
确认
|
||||
</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<!-- 物料选择弹窗 -->
|
||||
<MaterialSelectDialog ref="materialSelectRef" @confirm="handleMaterialConfirm" />
|
||||
|
||||
<!-- 入库单选择弹窗 -->
|
||||
<StorageSelectDialog ref="storageSelectRef" @confirm="handleStorageConfirm" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import * as RawStorageApi from '@/api/biz/rawstorage'
|
||||
import { watch } from 'vue'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import Dialog from '@/components/Dialog/src/Dialog.vue'
|
||||
import MoneyInput from '@/components/MoneyInput/src/MoneyInput.vue'
|
||||
import MaterialSelectDialog from './MaterialSelectDialog.vue'
|
||||
import StorageSelectDialog from './StorageSelectDialog.vue'
|
||||
import * as ReturnStorageApi from '@/api/biz/returnstorage'
|
||||
import { getUnitName } from '@/utils/dict'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
defineOptions({ name: 'ReturnStorageForm' })
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
const { t } = useI18n()
|
||||
const message = useMessage()
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('')
|
||||
const formLoading = ref(false)
|
||||
const formType = ref('')
|
||||
const formRef = ref()
|
||||
|
||||
// 表单数据
|
||||
const formData = reactive({
|
||||
id: undefined,
|
||||
billNo: undefined,
|
||||
operatorType: undefined,
|
||||
businessType: undefined,
|
||||
remark: undefined,
|
||||
status: undefined,
|
||||
supplierNo: undefined,
|
||||
billNo: '保存时自动生成',
|
||||
businessType: "3",
|
||||
billDate: new Date().toISOString().split('T')[0],
|
||||
status: '1',
|
||||
supplierName: undefined,
|
||||
supplierId: undefined,
|
||||
billDate: undefined,
|
||||
operatorId: undefined,
|
||||
operatorName: undefined,
|
||||
relarionNo: undefined,
|
||||
relarionId: undefined,
|
||||
billType: undefined,
|
||||
sourceNo: undefined,
|
||||
sourceId: undefined,
|
||||
remark: undefined,
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = reactive({
|
||||
businessType: [{ required: true, message: '请选择业务类型', trigger: 'change' }],
|
||||
billDate: [{ required: true, message: '请选择退料日期', trigger: 'change' }],
|
||||
})
|
||||
|
||||
// 明细列表
|
||||
const detailList = ref<any[]>([])
|
||||
|
||||
// 仓储选项
|
||||
const warehouseOptions = ref([])
|
||||
// 供应商选项
|
||||
const supplierOptions = ref([])
|
||||
|
||||
// 子组件 Ref
|
||||
const materialSelectRef = ref()
|
||||
const storageSelectRef = ref()
|
||||
|
||||
/** 弹窗关闭时通知父组件 */
|
||||
watch(dialogVisible, (val) => {
|
||||
if (!val) {
|
||||
@ -112,49 +293,237 @@ watch(dialogVisible, (val) => {
|
||||
}
|
||||
})
|
||||
|
||||
const formRules = reactive({
|
||||
billNo: [{ required: true, message: '单据编号不能为空', trigger: 'blur' }],
|
||||
operatorType: [{ required: true, message: '操作类型 1为入库,2为出库不能为空', trigger: 'blur' }],
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
dialogTitle.value = type === 'create' ? '新增' : type === 'update' ? '编辑' : '详情'
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
|
||||
await loadWarehouseList()
|
||||
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await RawStorageApi.getRawStorage(id)
|
||||
const data = await ReturnStorageApi.getReturnStorage(id)
|
||||
Object.assign(formData, data)
|
||||
detailList.value = data.items || []
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
defineExpose({ open })
|
||||
|
||||
/** 加载仓储列表 */
|
||||
const loadWarehouseList = async () => {
|
||||
try {
|
||||
const data = await ReturnStorageApi.getWarehouseSelect()
|
||||
warehouseOptions.value = data.list || []
|
||||
} catch (error) {
|
||||
console.error('加载仓储列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/** 加载供应商列表 */
|
||||
const loadSupplierList = async () => {
|
||||
try {
|
||||
const data = await ReturnStorageApi.getSupplierSelect()
|
||||
supplierOptions.value = data.list || []
|
||||
} catch (error) {
|
||||
console.error('加载供应商列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/** 打开物料选择弹窗 */
|
||||
const openMaterialSelect = () => {
|
||||
materialSelectRef.value.open()
|
||||
}
|
||||
|
||||
/** 打开入库单选择弹窗 */
|
||||
const openStorageSelect = () => {
|
||||
storageSelectRef.value.open()
|
||||
}
|
||||
|
||||
/** 处理物料确认选择 */
|
||||
const handleMaterialConfirm = (selectedMaterials: any[]) => {
|
||||
selectedMaterials.forEach((material) => {
|
||||
const exists = detailList.value.some(
|
||||
(item) => item.materialId === material.id,
|
||||
)
|
||||
|
||||
if (!exists) {
|
||||
detailList.value.push({
|
||||
id: undefined,
|
||||
description: undefined,
|
||||
storeHouseId: undefined,
|
||||
storeAreaId: undefined,
|
||||
storeHouseCd: undefined,
|
||||
storeHouseName: undefined,
|
||||
storeAreCd: undefined,
|
||||
storeAreaName: undefined,
|
||||
materialId: material.id,
|
||||
matName: material.matName,
|
||||
matCode: material.matCode,
|
||||
spec: material.spec,
|
||||
unit: material.unit,
|
||||
lotNo: undefined,
|
||||
returnQty: undefined,
|
||||
sourceQty: material.purQty || 0,
|
||||
returnedQty: 0,
|
||||
inDate: material.inDate,
|
||||
inventBillNo: material.inventBillNo,
|
||||
sourceId: undefined,
|
||||
relarionId: undefined,
|
||||
areaOptions: [],
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 处理入库单确认选择 */
|
||||
const handleStorageConfirm = (storages: any[]) => {
|
||||
// 清空之前的明细数据
|
||||
detailList.value = []
|
||||
|
||||
// 设置关联入库单号
|
||||
formData.relarionNo = storages[0]?.billNo || ''
|
||||
formData.relarionId = storages[0]?.stockId || ''
|
||||
|
||||
// 遍历选中的入库物料明细
|
||||
storages.forEach((storage) => {
|
||||
detailList.value.push({
|
||||
id: storage.id,
|
||||
description: undefined,
|
||||
storeHouseId: storage.storeHouseId,
|
||||
storeAreaId: storage.storeAreaId,
|
||||
storeHouseCd: storage.storeHouseCd,
|
||||
storeHouseName: storage.storeHouseName,
|
||||
storeAreCd: storage.storeAreCd,
|
||||
storeAreaName: storage.storeAreaName,
|
||||
materialId: storage.materialId,
|
||||
matName: storage.matName,
|
||||
matCode: storage.matCode,
|
||||
spec: storage.spec,
|
||||
unit: storage.unit,
|
||||
lotNo: storage.lotNo,
|
||||
returnQty: undefined,
|
||||
sourceQty: storage.operatorQty || 0,
|
||||
returnedQty: storage.returnedQty || 0,
|
||||
inDate: storage.billDate,
|
||||
inventBillNo: storage.inventBillNo,
|
||||
sourceId: storage.stockId,
|
||||
relarionId: storage.stockId,
|
||||
areaOptions: [],
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除明细 */
|
||||
const handleDeleteDetail = (index: number) => {
|
||||
detailList.value.splice(index, 1)
|
||||
}
|
||||
|
||||
/** 处理仓储变化,重新加载库区 */
|
||||
const handleWarehouseChange = async (row: any) => {
|
||||
row.storeAreaId = undefined
|
||||
row.storeAreaName = undefined
|
||||
row.storeAreCd = undefined
|
||||
|
||||
if (row.storeHouseId) {
|
||||
const warehouse = warehouseOptions.value.find((w: any) => w.id === row.storeHouseId)
|
||||
if (warehouse) {
|
||||
row.storeHouseCd = warehouse.storeHouseCd
|
||||
row.storeHouseName = warehouse.storeHouseName
|
||||
}
|
||||
|
||||
try {
|
||||
const list = await AreaApi.getStoreArea(row.storeHouseId)
|
||||
row.areaOptions = (list || []).map((area: any) => ({
|
||||
...area,
|
||||
id: Number(area.id)
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('加载库区列表失败:', error)
|
||||
row.areaOptions = []
|
||||
}
|
||||
} else {
|
||||
row.areaOptions = []
|
||||
row.storeHouseCd = undefined
|
||||
row.storeHouseName = undefined
|
||||
}
|
||||
}
|
||||
|
||||
/** 处理库区变化 */
|
||||
const handleAreaChange = (row: any) => {
|
||||
const area = row.areaOptions?.find((a: any) => a.id === row.storeAreaId)
|
||||
if (area) {
|
||||
row.storeAreCd = area.storeAreCd
|
||||
row.storeAreaName = area.storeAreaName
|
||||
}
|
||||
}
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success', 'close']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
const emit = defineEmits(['success', 'close'])
|
||||
|
||||
const handleSubmit = async (action: string) => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
// 提交请求
|
||||
|
||||
// 校验明细
|
||||
if (detailList.value.length === 0) {
|
||||
message.error('请至少添加一条明细')
|
||||
return
|
||||
}
|
||||
|
||||
// 校验退料数量
|
||||
for (const item of detailList.value) {
|
||||
if (!item.returnQty || item.returnQty <= 0) {
|
||||
message.error('请完善退料数量')
|
||||
return
|
||||
}
|
||||
|
||||
// 退料数量 + 已退料数量 <= 入库数量
|
||||
const totalReturn = (item.returnQty || 0) + (item.returnedQty || 0)
|
||||
if (totalReturn > (item.sourceQty || 0)) {
|
||||
message.error(`退料数量 + 已退料数量不能大于入库数量(${item.matName})`)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as RawStorageApi.RawStorageVO
|
||||
const submitData = {
|
||||
...formData,
|
||||
items: detailList.value.map(item => ({
|
||||
...item,
|
||||
areaOptions: undefined // 不提交临时字段
|
||||
}))
|
||||
}
|
||||
|
||||
if (action === 'save') {
|
||||
if (formType.value === 'create') {
|
||||
await RawStorageApi.createRawStorage(data)
|
||||
await ReturnStorageApi.createReturnStorage(submitData)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await RawStorageApi.updateRawStorage(data)
|
||||
await ReturnStorageApi.updateReturnStorage(submitData)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
} else {
|
||||
// 确认操作
|
||||
if (formType.value === 'create') {
|
||||
await ReturnStorageApi.confirmReturnStorage(submitData)
|
||||
message.success('确认成功')
|
||||
} else {
|
||||
await ReturnStorageApi.confirmReturnStorage(submitData)
|
||||
message.success('确认成功')
|
||||
}
|
||||
}
|
||||
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} catch (error) {
|
||||
console.error('提交失败:', error)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
@ -162,25 +531,25 @@ const submitForm = async () => {
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
Object.assign(formData, {
|
||||
id: undefined,
|
||||
billNo: undefined,
|
||||
operatorType: undefined,
|
||||
businessType: undefined,
|
||||
remark: undefined,
|
||||
status: undefined,
|
||||
supplierNo: undefined,
|
||||
billNo: '保存时自动生成',
|
||||
businessType: "3",
|
||||
billDate: new Date().toISOString().split('T')[0],
|
||||
status: '1',
|
||||
supplierName: undefined,
|
||||
supplierId: undefined,
|
||||
billDate: undefined,
|
||||
operatorId: undefined,
|
||||
operatorName: undefined,
|
||||
relarionNo: undefined,
|
||||
relarionId: undefined,
|
||||
billType: undefined,
|
||||
sourceNo: undefined,
|
||||
sourceId: undefined,
|
||||
}
|
||||
remark: undefined,
|
||||
})
|
||||
detailList.value = []
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(() => {
|
||||
loadWarehouseList()
|
||||
loadSupplierList()
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<Dialog :title="'选择入库单'" v-model="dialogVisible" width="90%">
|
||||
<el-form :model="queryParams" inline label-width="80px">
|
||||
<el-form-item label="入库单号">
|
||||
<el-input
|
||||
v-model="queryParams.billNo"
|
||||
placeholder="请输入"
|
||||
clearable
|
||||
@keyup.enter="getList"
|
||||
class="!w-200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="物料名称">
|
||||
<el-input
|
||||
v-model="queryParams.matName"
|
||||
placeholder="请输入"
|
||||
clearable
|
||||
@keyup.enter="getList"
|
||||
class="!w-200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="getList"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div style="max-height: 500px; overflow-y: auto; margin-top: 15px;">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
:stripe="true"
|
||||
:show-overflow-tooltip="true"
|
||||
border
|
||||
:highlight-current-row="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleRowDoubleClick"
|
||||
style="width: 100%;"
|
||||
>
|
||||
<el-table-column type="selection" width="45px" align="center" />
|
||||
<el-table-column label="序号" type="index" width="60px" align="center" />
|
||||
<el-table-column label="入库单号" align="center" prop="billNo" />
|
||||
<el-table-column label="单据类型" align="center" prop="businessType" width="100px">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.businessType === '10'">采购入库</span>
|
||||
<span v-else-if="scope.row.businessType === '11'">盘盈入库</span>
|
||||
<span v-else-if="scope.row.businessType === '12'">其它入库</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="入库日期" align="center" prop="billDate" width="110px" />
|
||||
<el-table-column label="物料编码" align="center" prop="matCode" />
|
||||
<el-table-column label="物料名称" align="center" prop="matName" />
|
||||
<el-table-column label="入库数量" align="center" prop="operatorQty" />
|
||||
<el-table-column label="已退货数量" align="center" prop="returnQty" />
|
||||
<el-table-column label="规格型号" align="center" prop="spec" />
|
||||
<el-table-column label="批次号" align="center" prop="lotNo" />
|
||||
<el-table-column label="仓储名称" align="center" prop="storeHouseName" />
|
||||
<el-table-column label="库区名称" align="center" prop="storeAreaName" />
|
||||
<el-table-column label="存货账单号" align="center" prop="inventBillNo" />
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: flex-end; margin-top: 10px;">
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm" :disabled="selectedItems.length === 0">保存</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import Dialog from '@/components/Dialog/src/Dialog.vue'
|
||||
import Pagination from '@/components/Pagination/index.vue'
|
||||
import * as RawStorageMatApi from '@/api/biz/rawstoragemat'
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const loading = ref(false)
|
||||
const list = ref([])
|
||||
const total = ref(0)
|
||||
const selectedItems = ref([])
|
||||
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
billNo: undefined,
|
||||
matName: undefined,
|
||||
})
|
||||
|
||||
const emit = defineEmits(['confirm'])
|
||||
|
||||
const open = () => {
|
||||
dialogVisible.value = true
|
||||
selectedItems.value = []
|
||||
getList()
|
||||
}
|
||||
defineExpose({ open })
|
||||
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await RawStorageMatApi.getRawStorageMatPage(queryParams)
|
||||
list.value = data.list || []
|
||||
total.value = data.total || 0
|
||||
} catch (error) {
|
||||
console.error('获取入库物料明细列表失败:', error)
|
||||
list.value = []
|
||||
total.value = 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const resetQuery = () => {
|
||||
queryParams.billNo = undefined
|
||||
queryParams.matName = undefined
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
const handleSelectionChange = (val: any[]) => {
|
||||
selectedItems.value = val
|
||||
}
|
||||
|
||||
const handleRowDoubleClick = (row: any) => {
|
||||
selectedItems.value = [row]
|
||||
emit('confirm', [row])
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
const handleConfirm = () => {
|
||||
if (selectedItems.value.length > 0) {
|
||||
emit('confirm', selectedItems.value)
|
||||
dialogVisible.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
@ -21,7 +21,16 @@
|
||||
<el-form-item label="退料单号" prop="billNo">
|
||||
<el-input
|
||||
v-model="queryParams.billNo"
|
||||
placeholder="请输入退料单号"
|
||||
placeholder="请输入"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="供应商" prop="supplierName">
|
||||
<el-input
|
||||
v-model="queryParams.supplierName"
|
||||
placeholder="请输入"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-200px"
|
||||
@ -30,7 +39,7 @@
|
||||
<el-form-item label="单据状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="请选择单据状态"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
class="!w-150px"
|
||||
>
|
||||
@ -41,6 +50,8 @@
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="openForm('create')"
|
||||
@ -69,13 +80,14 @@
|
||||
max-height="100%"
|
||||
>
|
||||
<el-table-column label="序号" align="center" type="index" width="60px"/>
|
||||
<el-table-column label="业务类型" align="center" prop="businessType" >
|
||||
<el-table-column label="单据类型" align="center" prop="businessType" >
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.businessType === '23'">标准采购退料</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退料单号" align="center" prop="billNo" />
|
||||
<el-table-column label="供应商" align="center" prop="supplierName" />
|
||||
<el-table-column label="单据状态" align="center" prop="status" >
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.status === '1'" class="text-blue">已创建</span>
|
||||
@ -85,7 +97,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="退料日期" align="center" prop="billDate" />
|
||||
<el-table-column label="退料人员" align="center" prop="operatorName" />
|
||||
<el-table-column label="其它入库单号" align="center" prop="relarionNo" />
|
||||
<el-table-column label="采购入库单号" align="center" prop="relarionNo" />
|
||||
<el-table-column label="操作" align="center" >
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
@ -143,10 +155,10 @@
|
||||
style="width: 100%;"
|
||||
>
|
||||
<el-table-column label="序号" align="center" type="index" width="60px"/>
|
||||
<el-table-column label="物料编码" align="center" prop="materialCode" />
|
||||
<el-table-column label="物料名称" align="center" prop="materialName" />
|
||||
<el-table-column label="物料编码" align="center" prop="matCode" />
|
||||
<el-table-column label="物料名称" align="center" prop="matName" />
|
||||
<el-table-column label="规格型号" align="center" prop="spec" />
|
||||
<el-table-column label="来源数量" align="center" prop="sourceQty" />
|
||||
<el-table-column label="收货数量" align="center" prop="sourceQty" />
|
||||
<el-table-column label="已退料数量" align="center" prop="returnedQty" />
|
||||
<el-table-column label="退料数量" align="center" prop="returnQty" />
|
||||
<el-table-column label="批次号" align="center" prop="lotNo" />
|
||||
@ -163,11 +175,11 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import * as RawStorageApi from '@/api/biz/rawstorage'
|
||||
import RawStorageForm from './RawStorageForm.vue'
|
||||
import * as ReturnStorageApi from '@/api/biz/returnstorage'
|
||||
import ReturnStorageForm from './ReturnStorageForm.vue'
|
||||
import { getUnitName } from '@/utils/dict'
|
||||
|
||||
defineOptions({ name: 'RawStorage' })
|
||||
defineOptions({ name: 'ReturnStorage' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
@ -191,7 +203,7 @@ const queryFormRef = ref() // 搜索的表单
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await RawStorageApi.getRawStoragePage(queryParams)
|
||||
const data = await ReturnStorageApi.getReturnStoragePage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
// 默认选中第一行并加载详情
|
||||
@ -208,7 +220,7 @@ const getDetailList = async (id: number) => {
|
||||
detailLoading.value = true
|
||||
try {
|
||||
// 根据退料单ID查询明细
|
||||
const data = await RawStorageApi.getRawStorage(id)
|
||||
const data = await ReturnStorageApi.getReturnStorage(id)
|
||||
// 后端返回的数据中,明细在items字段中
|
||||
detailList.value = data?.items || []
|
||||
} catch (error) {
|
||||
@ -270,12 +282,12 @@ const getDetailSummary = (param: any) => {
|
||||
columns.forEach((column: any, index: number) => {
|
||||
if (index === 0) {
|
||||
sums[index] = '合计'
|
||||
} else if (index === 4) {
|
||||
// 第5列:来源数量
|
||||
} else if (index === 5) {
|
||||
// 第 6 列:收货数量
|
||||
const total = data.reduce((sum: number, item: any) => sum + (Number(item.sourceQty) || 0), 0)
|
||||
sums[index] = total
|
||||
} else if (index === 6) {
|
||||
// 第7列:退料数量
|
||||
} else if (index === 7) {
|
||||
// 第 8 列:退料数量
|
||||
const total = data.reduce((sum: number, item: any) => sum + (Number(item.returnQty) || 0), 0)
|
||||
sums[index] = total
|
||||
} else {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user