库存单价管理

This commit is contained in:
z 2025-02-25 10:19:42 +08:00
parent 5d6a735402
commit 46ee4cbfc9
18 changed files with 319 additions and 12 deletions

View File

@ -117,7 +117,9 @@ public class MaterialRespVO {
@Schema(description = "库存预警下限")
@ExcelProperty("库存预警下限")
private BigDecimal invLowerLimit;
@Schema(description = "库存单价")
@ExcelProperty("库存单价")
private BigDecimal price;
@Schema(description = "物料条码")
@ExcelProperty("物料条码")
private String barcode;

View File

@ -80,7 +80,8 @@ public class MaterialSaveReqVO {
@Schema(description = "库存预警上限")
private BigDecimal invUpperLimit;
@Schema(description = "库存单价")
private BigDecimal price;
@Schema(description = "库存预警下限")
private BigDecimal invLowerLimit;

View File

@ -1,10 +1,18 @@
package com.chanko.yunxi.mes.module.heli.controller.admin.storage;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.chanko.yunxi.mes.module.heli.controller.admin.outsourcestockboom.vo.OutsourceStockBoomSaveReqVO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.material.MaterialDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelog.StorageLogDO;
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.mysql.material.MaterialMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.storagelog.StorageLogNowMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.storagemat.StorageMatMapper;
import com.chanko.yunxi.mes.module.heli.service.storagelog.StorageLogService;
import com.chanko.yunxi.mes.module.heli.service.storagemat.StorageMatService;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
@ -17,6 +25,7 @@ import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.io.IOException;
@ -50,7 +59,12 @@ public class StorageController {
@Resource
private StorageLogService storageLogService;
@Resource
private StorageMatMapper storageMatMapper;
@Resource
private StorageLogNowMapper storageLogNowMapper;
@Resource
private MaterialMapper materialMapper;
@PostMapping("/cancelWeiWai")
@Operation(summary = "委外取消提交")
@PreAuthorize("@ss.hasPermission('heli:storage:create')")
@ -125,6 +139,54 @@ public class StorageController {
storageService.updateStorage(updateReqVO);
int status = targetDo.getStatus();
if (updateReqVO.getStockType()==1&&updateReqVO.getStockInType()==1){
if (status==2){
List<StorageMatDO> matList = storageMatMapper.selectMatByStorckID(targetDo.getId());
for (StorageMatDO storageMatDO : matList) {
LambdaQueryWrapper<StorageLogNowDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(StorageLogNowDO::getMatCode, storageMatDO.getMatCode());
wrapper.eq(StorageLogNowDO::getMatName,storageMatDO.getMatName());
BigDecimal totalStorageOkQty = storageLogNowMapper.selectList(wrapper).stream()
.map(StorageLogNowDO::getStorageOkQty)
.filter(Objects::nonNull) // 确保过滤掉 null
.reduce(BigDecimal.ZERO, BigDecimal::add);
LambdaQueryWrapper<MaterialDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MaterialDO::getCode, storageMatDO.getMatCode());
queryWrapper.eq(MaterialDO::getName,storageMatDO.getMatName());
MaterialDO materialDO = materialMapper.selectOne(queryWrapper);
if (ObjectUtil.isEmpty(materialDO.getPrice())){
materialDO.setPrice(BigDecimal.ZERO);
}
BigDecimal add = totalStorageOkQty.multiply(materialDO.getPrice()).add(storageMatDO.getPrice());
BigDecimal divide = add.divide(totalStorageOkQty.add(storageMatDO.getStorageOkQty()),2,RoundingMode.HALF_UP);
materialDO.setPrice(divide);
materialMapper.updateById(materialDO);
}
}else if (status==3){
List<StorageMatDO> matList = storageMatMapper.selectMatByStorckID(targetDo.getId());
for (StorageMatDO storageMatDO : matList) {
LambdaQueryWrapper<StorageLogNowDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(StorageLogNowDO::getMatCode, storageMatDO.getMatCode());
wrapper.eq(StorageLogNowDO::getMatName,storageMatDO.getMatName());
BigDecimal totalStorageOkQty = storageLogNowMapper.selectList(wrapper).stream()
.map(StorageLogNowDO::getStorageOkQty)
.filter(Objects::nonNull) // 确保过滤掉 null
.reduce(BigDecimal.ZERO, BigDecimal::add);
LambdaQueryWrapper<MaterialDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MaterialDO::getCode, storageMatDO.getMatCode());
queryWrapper.eq(MaterialDO::getName,storageMatDO.getMatName());
MaterialDO materialDO = materialMapper.selectOne(queryWrapper);
if (ObjectUtil.isEmpty(materialDO.getPrice())){
materialDO.setPrice(BigDecimal.ZERO);
}
BigDecimal add = totalStorageOkQty.multiply(materialDO.getPrice()).subtract(storageMatDO.getPrice());
BigDecimal divide = add.divide(totalStorageOkQty.subtract(storageMatDO.getStorageOkQty()),2,RoundingMode.HALF_UP);
materialDO.setPrice(divide);
materialMapper.updateById(materialDO);
}
}
}
//状态说明1保存 2提交 3作废 4已审批
if(updateReqVO.getStockType() == 2){
//盘亏出库以外直接出

View File

@ -56,7 +56,13 @@ public class StorageLogController {
storageLogService.updateStorageLog(updateReqVO);
return success(true);
}
@PostMapping("/updatePrice")
@Operation(summary = "更新库存单价")
@PreAuthorize("@ss.hasPermission('heli:storage-log:update')")
public CommonResult<Boolean> updatePrice( @RequestBody StorageLogSaveReqVO updateReqVO) {
storageLogService.updatePrice(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除入/出库日志")
@Parameter(name = "id", description = "编号", required = true)
@ -114,6 +120,13 @@ public class StorageLogController {
PageResult<StorageLogNowDO> pageResult = storageLogService.getStorageNowPage(pageReqVO);
return success(pageResult);
}
@GetMapping("/price")
@Operation(summary = "获得库存单价分页")
@PreAuthorize("@ss.hasPermission('heli:storage-log:query')")
public CommonResult<PageResult<StorageLogNowDO>> getStorageNowPricePage(@Valid StorageLogPageReqVO pageReqVO) {
PageResult<StorageLogNowDO> pageResult = storageLogService.getStorageNowPricePage(pageReqVO);
return success(pageResult);
}
// @GetMapping("/nowsmall")
// @Operation(summary = "获得入/出库实时分页")
// @PreAuthorize("@ss.hasPermission('heli:storage-log:query')")

View File

@ -45,5 +45,9 @@ public class StorageLogSaveReqVO {
@Schema(description = "状态", example = "你说的对")
private Integer status;
@Schema(description = "物料编码", example = "你说的对")
private String matCode;
@Schema(description = "库存单价")
private BigDecimal price;
}

View File

@ -41,7 +41,9 @@ public class StorageMatRespVO {
@Schema(description = "库存良品数量")
@ExcelProperty("库存良品数量")
private BigDecimal storageOkQty;
@Schema(description = "库存价格")
@ExcelProperty("库存价格")
private BigDecimal price;
@Schema(description = "批次号")
@ExcelProperty("批次号")
private String lotNo;

View File

@ -37,7 +37,8 @@ public class StorageMatSaveReqVO {
@Schema(description = "库存良品数量")
private BigDecimal storageOkQty;
@Schema(description = "库存价格")
private BigDecimal price;
@Schema(description = "批次号")
private String lotNo;

View File

@ -119,6 +119,10 @@ public class MaterialDO extends TenantBaseDO {
* 库存预警上限
*/
private BigDecimal invUpperLimit;
/**
* 库存单价
*/
private BigDecimal price;
/**
* 库存预警下限
*/

View File

@ -30,9 +30,7 @@ public class StorageLogNowDO extends BaseDO {
private Long id;
private BigDecimal storageOkQty;
private String lotNo;
private String matName;
private String shortName;
private String matCode;
@ -55,7 +53,10 @@ public class StorageLogNowDO extends BaseDO {
@TableField(exist = false)
private Long materialTypeId;
@TableField(exist = false)
private BigDecimal price;
@TableField(exist = false)
private BigDecimal storageOkQtys;
@TableField(exist = false)
private Long matUnitId;

View File

@ -52,6 +52,10 @@ public class StorageMatDO extends BaseDO {
* 库存良品数量
*/
private BigDecimal storageOkQty;
/**
* 库存价格
*/
private BigDecimal price;
/**
* 批次号
*/

View File

@ -107,4 +107,21 @@ public interface StorageLogNowMapper extends BaseMapperX<StorageLogNowDO> {
List<StorageLogNowDO> selectNowByMatPnId(@Param("matId")Long matId,@Param("pnId")Long pnId);
default PageResult<StorageLogNowDO> getStorageNowPricePage(StorageLogPageReqVO reqVO) {
MPJLambdaWrapper<StorageLogNowDO> query = new MPJLambdaWrapper<>();
query.selectAll(StorageLogNowDO.class)
.select("COALESCE(SUM(storage_ok_qty), 0) as storageOkQtys,a.price as price")
.leftJoin(MaterialDO.class,"a",MaterialDO::getCode,StorageLogNowDO::getMatCode)
.groupBy(StorageLogNowDO::getMatCode)
.orderByDesc(StorageLogNowDO::getId);
query.like(!StringUtils.isEmpty(reqVO.getMatType()),StorageLogNowDO::getMatType, reqVO.getMatType())
.ne(true,StorageLogNowDO::getStorageOkQty,0)
.like(!StringUtils.isEmpty(reqVO.getMatName()), StorageLogNowDO::getMatName, reqVO.getMatName())
.like(!StringUtils.isEmpty(reqVO.getMatCode()), StorageLogNowDO::getMatCode, reqVO.getMatCode());
return selectPage(reqVO,query);
}
}

View File

@ -71,4 +71,7 @@ public interface StorageLogService {
void createStorageLogBatch(List<StorageLogDO> storageLogDOs);
PageResult<StorageLogNowDO> getStorageNowPricePage(StorageLogPageReqVO pageReqVO);
void updatePrice(StorageLogSaveReqVO updateReqVO);
}

View File

@ -1,5 +1,6 @@
package com.chanko.yunxi.mes.module.heli.service.storagelog;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.bdgzsomthing.bdgzsomthingDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.material.MaterialDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogAll.StorageLogAllDO;
@ -163,6 +164,19 @@ public class StorageLogServiceImpl implements StorageLogService {
}
@Override
public PageResult<StorageLogNowDO> getStorageNowPricePage(StorageLogPageReqVO pageReqVO) {
return storageLogNowMapper.getStorageNowPricePage(pageReqVO);
}
@Override
public void updatePrice(StorageLogSaveReqVO updateReqVO) {
LambdaUpdateWrapper<MaterialDO> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(MaterialDO::getCode,updateReqVO.getMatCode());
wrapper.set(MaterialDO::getPrice,updateReqVO.getPrice());
materialMapper.update(wrapper);
}
}

View File

@ -13,6 +13,7 @@ export interface StorageLogVO {
noZero: number
matCode: string
matType:string
price:number
}
@ -41,6 +42,10 @@ export const getStorageNowAllPage = async (params) => {
export const getStorageNowPage = async (params) => {
return await request.get({ url: `/heli/storage-log/now`, params })
}
// 查询库存单价分页
export const getStorageNowPricePage = async (params) => {
return await request.get({ url: `/heli/storage-log/price`, params })
}
// 查询入/出库实时分页
export const getStorageNowPagesmall = async (params) => {
@ -62,7 +67,10 @@ export const getStorageLog = async (id: number) => {
export const createStorageLog = async (data: StorageLogVO) => {
return await request.post({ url: `/heli/storage-log/create`, data })
}
//修改物料单价
export const updatePrice = async (data: StorageLogVO) => {
return await request.post({ url: `/heli/storage-log/updatePrice`, data })
}
// 修改入/出库日志
export const updateStorageLog = async (data: StorageLogVO) => {
return await request.put({ url: `/heli/storage-log/update`, data })

View File

@ -8,6 +8,7 @@ export interface StorageMatVO {
rgId: number
pnId: number
storageOkQty: number
price: number
lotNo: string
projectNo: string
description: string

View File

@ -256,12 +256,16 @@ const submitForm = async () => {
return false
}
}
if (formData.value.cgYishou!=''&&formData.value.cgYishou!=undefined){
if (formData.value.cgYishou!=''&&formData.value.cgYishou!=undefined&&formData.value.cgYishou!=null){
if (formData.value.cgYishou<formData.value.cgYs&&formData.value.cgTypee==2){
await message.confirm("已收金额小于应收金额,回款未完成,请确认")
}else if (formData.value.cgYishou>=formData.value.cgYs&&formData.value.cgTypee==1){
await message.confirm("已收金额大于等于应收金额,回款已完成,请确认")
}
}else {
if (formData.value.cgTypee==2){
await message.confirm("未输入已收金额,回款未完成,请确认")
}
}
//
formLoading.value = true

View File

@ -177,6 +177,28 @@
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="price" align="center" min-width="120" v-if="formData.stockInType=='1'">
<template #header> <span class="hl-table_header">*</span> 入库价格 </template>
<template #default="scope">
<el-form-item :prop="`${scope.$index}.price`" :rules="subFormRules.price"
class="mb-0px!">
<el-input v-model="scope.row.price" v-bind:disabled="ctrView || ctrSave" />
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="price" align="center" min-width="120" v-if="formData.stockInType!='1'">
<template #header>入库价格 </template>
<template #default="scope">
<el-form-item :prop="`${scope.$index}.price`"
class="mb-0px!">
<el-input v-model="scope.row.price" v-bind:disabled="ctrView || ctrSave" />
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="lotNo" label="批次号" align="center" min-width="120" v-if="false">
<template #default="scope">
@ -395,7 +417,9 @@ const subFormRules = reactive({
matCode: [{ required: true, message: '物料编码不能为空', trigger: 'blur' }],
rgId: [{ required: true, message: '库区不能为空', trigger: 'blur' }],
pnId: [{ required: true, message: '库位不能为空', trigger: 'blur' }],
storageOkQty: [{ required: true, message: '入库数量不能为空', trigger: 'blur' }]
storageOkQty: [{ required: true, message: '入库数量不能为空', trigger: 'blur' }],
price: [{ required: true, message: '入库价格不能为空', trigger: 'blur' }]
})
const matOpenFormRef = ref()

View File

@ -0,0 +1,142 @@
<template>
<el-card class="hl-card">
<template #header>
<span>库存单价管理</span>
</template>
<ContentWrap class="borderxx">
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="108px">
<el-form-item label="物料编码" prop="matCode">
<el-input v-model="queryParams.matCode" placeholder="物料编码" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="物料名称" prop="matName">
<el-input v-model="queryParams.matName" placeholder="物料名称" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="物料类型" prop="matType">
<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 style="margin-left:15px">
<el-button @click="handleQuery" type="primary">
<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>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" class="hl-table">
<el-table-column type="index" width="100" fixed label="序号" align="center" />
<el-table-column label="物料名称" align="center" prop="matName" fixed min-width="120"/>
<el-table-column label="物料编码" align="center" prop="matCode" fixed min-width="120" />
<el-table-column label="物料类型" align="center" prop="matType" min-width="120"/>
<el-table-column label="库存数量" align="center" prop="storageOkQtys" min-width="120"/>
<el-table-column label="库存单位" align="center" prop="matUnit" min-width="120"/>
<el-table-column label="库存金额(元)" align="center" prop="price" min-width="120">
<template #default="scope">
<el-input-number v-model="scope.row.price" type="number" :precision="2" />
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
type="primary"
link
@click="updatePrice(scope.row)"
>
修改金额
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>
</el-card>
</template>
<script setup lang="ts">
import download from '@/utils/download'
import * as StorageLogApi from '@/api/heli/storagelog'
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'
import {getStorageNowPage, getStorageNowPricePage} from "@/api/heli/storagelog";
import * as ModelApi from "@/api/bpm/model";
defineOptions({ name: 'StorageLog' })
const whList = ref([])
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
matCode: undefined,
matName: undefined,
matType: undefined,
lotNo: undefined,
whId: undefined,
rgId:undefined,
pnId: undefined,
headerNo: undefined,
})
const queryFormRef = ref() //
const emit = defineEmits(['success'])
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await StorageLogApi.getStorageNowPricePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
const updatePrice = async (row) => {
try {
await message.confirm("是否修改当前物料"+row.matName+"库存金额?")
await StorageLogApi.updatePrice(row);
message.success(t('修改成功'))
await getList()
}catch {}
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 初始化 **/
onMounted(async () => {
await getList()
})
</script>