实时库存

实时库存
pull/2/head
siontion 9 months ago
parent 159def12f6
commit cb51402301

@ -1,6 +1,7 @@
package com.chanko.yunxi.mes.module.heli.controller.admin.storagelog; package com.chanko.yunxi.mes.module.heli.controller.admin.storagelog;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogAll.StorageLogAllDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogAll.StorageLogAllDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogNow.StorageLogNowDO;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -80,6 +81,14 @@ public class StorageLogController {
return success(pageResult); return success(pageResult);
} }
@GetMapping("/now")
@Operation(summary = "获得入/出库实时分页")
@PreAuthorize("@ss.hasPermission('heli:storage-log:query')")
public CommonResult<PageResult<StorageLogNowDO>> getStorageNowPage(@Valid StorageLogPageReqVO pageReqVO) {
PageResult<StorageLogNowDO> pageResult = storageLogService.getStorageNowPage(pageReqVO);
return success(pageResult);
}
@GetMapping("/export-excel") @GetMapping("/export-excel")
@Operation(summary = "导出入/出库日志 Excel") @Operation(summary = "导出入/出库日志 Excel")
@PreAuthorize("@ss.hasPermission('heli:storage-log:export')") @PreAuthorize("@ss.hasPermission('heli:storage-log:export')")

@ -37,6 +37,15 @@ public class StorageLogPageReqVO extends PageParam {
@Schema(description = "出入库类型") @Schema(description = "出入库类型")
private Integer stockType; private Integer stockType;
@Schema(description = "仓库")
private Long whId;
@Schema(description = "库区")
private Long rgId;
@Schema(description = "库位")
private Long pnId;
} }

@ -0,0 +1,59 @@
package com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogNow;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.chanko.yunxi.mes.framework.mybatis.core.dataobject.BaseDO;
import lombok.*;
import java.math.BigDecimal;
/**
* / DO
*
* @author
*/
@TableName("v_storage_material_now")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StorageLogNowDO extends BaseDO {
/**
* id
*/
@TableId
private Long id;
/**
*
*/
private BigDecimal storageOkQty;
/**
*
*/
private String lotNo;
private String matName;
private String matCode;
private String matType;
private Long whId;
private String whName;
private Long rgId;
private String rgName;
private Long pnId;
private String pnName;
private String shortName;
private String matSpec;
private String matBrand;
private String matUnit;
}

@ -37,7 +37,7 @@ public interface PnMapper extends BaseMapperX<PnDO> {
} }
default List<Map<String, Object>> selectSimpleList() { default List<Map<String, Object>> selectSimpleList() {
return selectMaps(new QueryWrapper<PnDO>().select("id", "pn_name").lambda()); return selectMaps(new QueryWrapper<PnDO>().select("id", "pn_name","rg_id").lambda());
} }
} }

@ -35,7 +35,7 @@ public interface RgMapper extends BaseMapperX<RgDO> {
default List<Map<String, Object>> selectSimpleList() { default List<Map<String, Object>> selectSimpleList() {
return selectMaps(new QueryWrapper<RgDO>().select("id", "rg_name").lambda()); return selectMaps(new QueryWrapper<RgDO>().select("id", "rg_name","wh_id").lambda());
} }

@ -0,0 +1,36 @@
package com.chanko.yunxi.mes.module.heli.dal.mysql.storagelog;
import com.alibaba.druid.util.StringUtils;
import com.chanko.yunxi.mes.framework.common.pojo.PageResult;
import com.chanko.yunxi.mes.framework.mybatis.core.mapper.BaseMapperX;
import com.chanko.yunxi.mes.module.heli.controller.admin.storagelog.vo.StorageLogPageReqVO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogNow.StorageLogNowDO;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.ibatis.annotations.Mapper;
/**
* / Mapper
*
* @author
*/
@Mapper
public interface StorageLogNowMapper extends BaseMapperX<StorageLogNowDO> {
default PageResult<StorageLogNowDO> selectPage(StorageLogPageReqVO reqVO) {
MPJLambdaWrapper<StorageLogNowDO> query = new MPJLambdaWrapper<>();
query.selectAll(StorageLogNowDO.class)
.orderByDesc(StorageLogNowDO::getId);
query.like(!StringUtils.isEmpty(reqVO.getMatType()),StorageLogNowDO::getMatType, reqVO.getMatType())
.eq(reqVO.getWhId()!= null,StorageLogNowDO::getWhId, reqVO.getWhId())
.eq(reqVO.getRgId()!= null,StorageLogNowDO::getRgId, reqVO.getRgId())
.eq(reqVO.getPnId()!= null,StorageLogNowDO::getPnId, reqVO.getPnId())
.like(!StringUtils.isEmpty(reqVO.getMatName()), StorageLogNowDO::getMatName, reqVO.getMatName())
.like(!StringUtils.isEmpty(reqVO.getMatCode()), StorageLogNowDO::getMatCode, reqVO.getMatCode())
.like(!StringUtils.isEmpty(reqVO.getLotNo()),StorageLogNowDO::getLotNo, reqVO.getLotNo());
return selectPage(reqVO,query);
}
PageResult<StorageLogNowDO> selectAllPage(StorageLogPageReqVO reqVO);
}

@ -7,6 +7,7 @@ import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelog.StorageLogDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogAll.StorageLogAllDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogAll.StorageLogAllDO;
import com.chanko.yunxi.mes.framework.common.pojo.PageResult; import com.chanko.yunxi.mes.framework.common.pojo.PageResult;
import com.chanko.yunxi.mes.framework.common.pojo.PageParam; import com.chanko.yunxi.mes.framework.common.pojo.PageParam;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogNow.StorageLogNowDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagemat.StorageMatDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagemat.StorageMatDO;
/** /**
@ -54,6 +55,8 @@ public interface StorageLogService {
*/ */
PageResult<StorageLogAllDO> getStorageLogPage(StorageLogPageReqVO pageReqVO); PageResult<StorageLogAllDO> getStorageLogPage(StorageLogPageReqVO pageReqVO);
PageResult<StorageLogNowDO> getStorageNowPage(StorageLogPageReqVO pageReqVO);
void createStorageLogBatch(List<StorageLogDO> storageLogDOs); void createStorageLogBatch(List<StorageLogDO> storageLogDOs);
} }

@ -1,7 +1,9 @@
package com.chanko.yunxi.mes.module.heli.service.storagelog; package com.chanko.yunxi.mes.module.heli.service.storagelog;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogAll.StorageLogAllDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogAll.StorageLogAllDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogNow.StorageLogNowDO;
import com.chanko.yunxi.mes.module.heli.dal.mysql.storagelog.StorageLogAllMapper; import com.chanko.yunxi.mes.module.heli.dal.mysql.storagelog.StorageLogAllMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.storagelog.StorageLogNowMapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -34,6 +36,9 @@ public class StorageLogServiceImpl implements StorageLogService {
@Resource @Resource
private StorageLogAllMapper storageLogAllMapper; private StorageLogAllMapper storageLogAllMapper;
@Resource
private StorageLogNowMapper storageLogNowMapper;
@Override @Override
public Long createStorageLog(StorageLogSaveReqVO createReqVO) { public Long createStorageLog(StorageLogSaveReqVO createReqVO) {
// 插入 // 插入
@ -76,6 +81,11 @@ public class StorageLogServiceImpl implements StorageLogService {
return storageLogAllMapper.selectPage(pageReqVO); return storageLogAllMapper.selectPage(pageReqVO);
} }
@Override
public PageResult<StorageLogNowDO> getStorageNowPage(StorageLogPageReqVO pageReqVO) {
return storageLogNowMapper.selectPage(pageReqVO);
}
@Override @Override
public void createStorageLogBatch(List<StorageLogDO> storageLogDOs) { public void createStorageLogBatch(List<StorageLogDO> storageLogDOs) {
for (StorageLogDO storageLogDo : storageLogDOs){ for (StorageLogDO storageLogDo : storageLogDOs){

@ -12,6 +12,11 @@ export interface StorageLogVO {
description: string description: string
} }
// 查询入/出库实时分页
export const getStorageNowPage = async (params) => {
return await request.get({ url: `/heli/storage-log/now`, params })
}
// 查询入/出库日志分页 // 查询入/出库日志分页
export const getStorageLogPage = async (params) => { export const getStorageLogPage = async (params) => {
return await request.get({ url: `/heli/storage-log/page`, params }) return await request.get({ url: `/heli/storage-log/page`, params })

@ -1,128 +1,170 @@
<template> <template>
<Dialog :title="dialogTitle" v-model="dialogVisible"> <ContentWrap>
<el-form <!-- 搜索工作栏 -->
ref="formRef" <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
:model="formData" <el-form-item label="物料编码" prop="matCode">
:rules="formRules" <el-input v-model="queryParams.matCode" placeholder="物料编码" clearable @keyup.enter="handleQuery"
label-width="100px" class="!w-240px" />
v-loading="formLoading"
>
<el-form-item label="入/出库Id" prop="stockId">
<el-input v-model="formData.stockId" placeholder="请输入入/出库Id" />
</el-form-item> </el-form-item>
<el-form-item label="物料 Id,对应 base_material表中的 Id 列" prop="matId"> <el-form-item label="物料名称" prop="matName">
<el-input v-model="formData.matId" placeholder="请输入物料 Id,对应 base_material表中的 Id 列" /> <el-input v-model="queryParams.matName" placeholder="物料名称" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item> </el-form-item>
<el-form-item label="仓库 Id对应 wms_wh 表中的Id" prop="whId"> <el-form-item label="物料类型" prop="matType">
<el-input v-model="formData.whId" placeholder="请输入仓库 Id对应 wms_wh 表中的Id" /> <el-select v-model="queryParams.matType" placeholder="下拉选择" clearable class="!w-240px">
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.HELI_MATERIAL_TYPE)" :key="dict.label" :label="dict.label"
:value="dict.label" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="库区 Id对应 wms_rg 表中的Id" prop="rgId"> <el-form-item label="批次号" prop="lotNo">
<el-input v-model="formData.rgId" placeholder="请输入库区 Id对应 wms_rg 表中的Id" /> <el-input v-model="queryParams.lotNo" placeholder="批次号" clearable @keyup.enter="handleQuery" class="!w-240px" />
</el-form-item> </el-form-item>
<el-form-item label="库区 Id对应 wms_rg 表中的Id" prop="pnId"> <el-form-item label="仓库" prop="whId">
<el-input v-model="formData.pnId" placeholder="请输入库区 Id对应 wms_rg 表中的Id" /> <el-select v-model="queryParams.whId" placeholder="下拉选择" clearable class="!w-240px" @change="handleWh">
<el-option v-for="dict in whList" :key="dict.id" :label="dict.wh_name"
:value="dict.id" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="库存良品数量" prop="storageOkQty"> <el-form-item label="库区" prop="rgId">
<el-input v-model="formData.storageOkQty" placeholder="请输入库存良品数量" /> <el-select v-model="queryParams.rgId" placeholder="下拉选择" clearable class="!w-240px" @change="handleRg">
<el-option v-for="dict in rgCurrentList" :key="dict.id" :label="dict.rg_name"
:value="dict.id" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="批次号" prop="lotNo"> <el-form-item label="库位" prop="pnId">
<el-input v-model="formData.lotNo" placeholder="请输入批次号" /> <el-select v-model="queryParams.pnId" placeholder="下拉选择" clearable class="!w-240px">
<el-option v-for="dict in pnCurrentList" :key="dict.id" :label="dict.pn_name"
:value="dict.id" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="备注" prop="description">
<el-input v-model="formData.description" type="textarea" placeholder="请输入备注" /> <el-form-item>
<el-button @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-form> </el-form>
<template #footer> </ContentWrap>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button> <!-- 列表 -->
</template> <ContentWrap>
</Dialog> <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="物料编码" align="center" prop="matCode" />
<el-table-column label="物料名称" align="center" prop="matName" />
<el-table-column label="物料类型" align="center" prop="matType" />
<el-table-column label="物料简称" align="center" prop="shortName" />
<el-table-column label="规格/型号" align="center" prop="matSpec" />
<el-table-column label="品牌" align="center" prop="matBrand" />
<el-table-column label="仓库" align="center" prop="whName" />
<el-table-column label="库区" align="center" prop="rgName" />
<el-table-column label="库位" align="center" prop="pnName" />
<el-table-column label="批次号" align="center" prop="lotNo" />
<el-table-column label="变动数量" align="center" prop="storageOkQty" />
<el-table-column label="库存单位" align="center" prop="matUnit" />
</el-table>
<!-- 分页 -->
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import download from '@/utils/download'
import * as StorageLogApi from '@/api/heli/storagelog' import * as StorageLogApi from '@/api/heli/storagelog'
const { t } = useI18n() // import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import * as WarehouseApi from '@/api/heli/warehouse'
import * as RgApi from '@/api/heli/rg'
import * as PnApi from '@/api/heli/pn'
defineOptions({ name: 'StorageLog' })
const whList = ref([])
const rgList = ref([])
const pnList = ref([])
const rgCurrentList = ref([])
const pnCurrentList = ref([])
const message = useMessage() // const message = useMessage() //
const { t } = useI18n() //
const dialogVisible = ref(false) // const loading = ref(true) //
const dialogTitle = ref('') // const list = ref([]) //
const formLoading = ref(false) // 12 const total = ref(0) //
const formType = ref('') // create - update - const queryParams = reactive({
const formData = ref({ pageNo: 1,
id: undefined, pageSize: 10,
stockId: undefined, matCode: undefined,
matId: undefined, matName: undefined,
matType: undefined,
lotNo: undefined,
whId: undefined, whId: undefined,
rgId:undefined, rgId:undefined,
pnId: undefined, pnId: undefined,
storageOkQty: undefined, headerNo: undefined,
lotNo: undefined,
description: undefined,
}) })
const formRules = reactive({ const queryFormRef = ref() //
stockId: [{ required: true, message: '入/出库Id不能为空', trigger: 'blur' }],
matId: [{ required: true, message: '物料 Id,对应 base_material表中的 Id 列不能为空', trigger: 'blur' }], /** 查询列表 */
whId: [{ required: true, message: '仓库 Id对应 wms_wh 表中的Id不能为空', trigger: 'blur' }], const getList = async () => {
rgId: [{ required: true, message: '库区 Id对应 wms_rg 表中的Id不能为空', trigger: 'blur' }], loading.value = true
pnId: [{ required: true, message: '库区 Id对应 wms_rg 表中的Id不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try { try {
formData.value = await StorageLogApi.getStorageLog(id) const data = await StorageLogApi.getStorageNowPage(queryParams)
list.value = data.list
total.value = data.total
} finally { } finally {
formLoading.value = false loading.value = false
} }
} }
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
} }
defineExpose({ open }) // open
/** 重置按钮操作 */
/** 提交表单 */ const resetQuery = () => {
const emit = defineEmits(['success']) // success queryFormRef.value.resetFields()
const submitForm = async () => { handleQuery()
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as StorageLogApi.StorageLogVO
if (formType.value === 'create') {
await StorageLogApi.createStorageLog(data)
message.success(t('common.createSuccess'))
} else {
await StorageLogApi.updateStorageLog(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
} }
/** 重置表单 */ const handleWh = async (wid) => {
const resetForm = () => { queryParams.rgId = undefined
formData.value = { queryParams.pnId = undefined
id: undefined,
stockId: undefined, rgCurrentList.value =[]
matId: undefined, pnCurrentList.value =[]
whId: undefined, rgCurrentList.value = rgList.value.filter( (item) => { return item.wh_id == wid})
rgId: undefined,
pnId: undefined,
storageOkQty: undefined,
lotNo: undefined,
description: undefined,
} }
formRef.value?.resetFields() const handleRg = async (rgid) => {
pnCurrentList.value =[]
pnCurrentList.value = pnList.value.filter( (item) => { return item.rg_id == rgid})
} }
//
const init_page_wh = (async ()=>{
whList.value = await WarehouseApi.getSimpList()
})
//
const init_page_rg = (async ()=>{
rgList.value = await RgApi.getSimpList()
})
//
const init_page_pn = (async ()=>{
pnList.value = await PnApi.getSimpList()
})
/** 初始化 **/
onMounted(async () => {
await init_page_wh()
await init_page_rg()
await init_page_pn()
await getList()
})
</script> </script>

@ -70,26 +70,23 @@
@pagination="getList" /> @pagination="getList" />
</ContentWrap> </ContentWrap>
<!-- 表单弹窗添加/修改 -->
<StorageLogForm ref="formRef" @success="getList" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import download from '@/utils/download' import download from '@/utils/download'
import * as StorageLogApi from '@/api/heli/storagelog' import * as StorageLogApi from '@/api/heli/storagelog'
import StorageLogForm from './StorageLogForm.vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import * as WarehouseApi from '@/api/heli/warehouse' // import * as WarehouseApi from '@/api/heli/warehouse'
import * as RgApi from '@/api/heli/rg' // import * as RgApi from '@/api/heli/rg'
import * as PnApi from '@/api/heli/pn' // import * as PnApi from '@/api/heli/pn'
defineOptions({ name: 'StorageLog' }) defineOptions({ name: 'StorageLog' })
const whList = ref([]) // const whList = ref([])
const rgList = ref([]) // const rgList = ref([])
const pnList = ref([]) // const pnList = ref([])
const message = useMessage() // const message = useMessage() //
const { t } = useI18n() // const { t } = useI18n() //
@ -134,24 +131,24 @@ const resetQuery = () => {
queryFormRef.value.resetFields() queryFormRef.value.resetFields()
handleQuery() handleQuery()
} }
// // //
const init_page_wh = (async ()=>{ // const init_page_wh = (async ()=>{
whList.value = await WarehouseApi.getSimpList() // whList.value = await WarehouseApi.getSimpList()
}) // })
// // //
const init_page_rg = (async ()=>{ // const init_page_rg = (async ()=>{
rgList.value = await RgApi.getSimpList() // rgList.value = await RgApi.getSimpList()
}) // })
// // //
const init_page_pn = (async ()=>{ // const init_page_pn = (async ()=>{
pnList.value = await PnApi.getSimpList() // pnList.value = await PnApi.getSimpList()
}) // })
/** 初始化 **/ /** 初始化 **/
onMounted(async () => { onMounted(async () => {
await init_page_wh() // await init_page_wh()
await init_page_rg() // await init_page_rg()
await init_page_pn() // await init_page_pn()
await getList() await getList()
}) })
</script> </script>
Loading…
Cancel
Save