库存补充

This commit is contained in:
z 2025-06-25 08:27:07 +08:00
parent 8f323c5038
commit 1d17fc5d3c
29 changed files with 741 additions and 29 deletions

View File

@ -52,6 +52,8 @@ public enum CodeEnum {
TASK_DISPATCH_ASSEMBLE("装配任务派工单", "ATD", 3, "yyyyMMdd"),
TASK_DISPATCH_GCJYPG("过程检验派工单", "GCJ", 4, "yyyyMMdd"),
TASK_DISPATCH_ZJJYPG("终检检验派工单", "ZJ", 4, "yyyyMMdd"),
MAT_REQ("领料单", "LL", 4, "yyyyMMdd"),
UNQUALIFIED_NOTIFICATION("品质异常通知单", "RN", 4, "yyyyMMdd"),
MATERIAL("物料", 6),
;

View File

@ -172,7 +172,7 @@ public class bdgzsomthingController {
@PostMapping("/getMessage")
@Operation(summary = "小程序消息")
@PreAuthorize("@ss.hasPermission('heli:bdgzsomthing:query')")
public CommonResult<PageResult<bdgzsomthingDO>> getMessage(@Valid bdgzsomthingPageReqVO pageReqVO) {
public CommonResult<PageResult<bdgzsomthingDO>> getMessage(@Valid @RequestBody bdgzsomthingPageReqVO pageReqVO) {
PageResult<bdgzsomthingDO>pageResult = bdgzsomthingService.getMessage(pageReqVO);
return success(BeanUtils.toBean(pageResult, bdgzsomthingDO.class));
}

View File

@ -122,4 +122,11 @@ public class MaterialController {
materialService.importExcel(list, updateSupport);
return success(null);
}
@GetMapping({"/getbzjList"})
@Operation(summary = "TODO:获取物料标准件信息列表", description = "只包含被开启的物料,主要用于前端的下拉选项")
public CommonResult<List<Map<String, Object>> > getbzjList() {
List<Map<String, Object>> list = materialService.getbzjList();
// 拼接数据
return success(list);
}
}

View File

@ -2,6 +2,7 @@ package com.chanko.yunxi.mes.module.heli.controller.admin.materialplan;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.materialplanboom.MaterialPlanBoomDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.processbom.ProcessBomDetailDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogNow.StorageLogNowDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.taskdispatch.TaskDispatchDetailDO;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@ -164,10 +165,31 @@ public class MaterialPlanController {
PageResult<MaterialPlanBoomDO> pageResult = materialPlanService.getStandardPartsPages(pageReqVO);
return success(pageResult);
}
@GetMapping("/exportStandardParts")
@Operation(summary = "导出标准件库存")
@PreAuthorize("@ss.hasPermission('heli:material-plan:export')")
@OperateLog(type = EXPORT)
public void exportStandardParts(@Valid MaterialPlanPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<MaterialPlanBoomDO> list = materialPlanService.getStandardPartsPages(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "标准件库存.xlsx", "数据", MaterialPlanBoomExcelVo.class,
BeanUtils.toBean(list, MaterialPlanBoomExcelVo.class));
}
@GetMapping("/operation")
@Operation(summary = "获得标准件库存")
@PreAuthorize("@ss.hasPermission('heli:material-plan:query')")
public CommonResult<Boolean> operation(@Valid MaterialPlanPageReqVO pageReqVO) {
return materialPlanService.operation(pageReqVO);
}
@PostMapping("/supplement")
@Operation(summary = "库存补充")
@PreAuthorize("@ss.hasPermission('heli:process-bom:create')")
public CommonResult<Boolean> supplement(@Valid @RequestBody List<StorageLogNowDO> list) {
return success(materialPlanService.supplement(list));
}
}

View File

@ -0,0 +1,45 @@
package com.chanko.yunxi.mes.module.heli.controller.admin.materialplan.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.chanko.yunxi.mes.framework.excel.core.annotations.DictFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.util.Date;
/**
* Excel 导入 VO
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false) // 设置 chain = false避免BOM导入有问题
public class MaterialPlanBoomExcelVo {
@ExcelProperty("项目名称")
private String projectName;
@ExcelProperty("子项目名称")
private String projectSubName;
@ExcelProperty("物料编码")
private String materialName;
@ExcelProperty("物料名称")
private String matName;
@ExcelProperty("规格型号")
private String boomSpec;
@ExcelProperty("图号")
private String blueprintNo;
@ExcelProperty("需求数量")
private String boomAmount;
@ExcelProperty("系统单位")
@DictFormat("heli_material_unit")
private String boomUnit;
@ExcelProperty("要求完成日期")
private String boomArriveDates;
}

View File

@ -84,7 +84,7 @@ public class MatReqController {
@Operation(summary = "领料单生成")
@PreAuthorize("@ss.hasPermission('heli:process-bom:create')")
public CommonResult<Boolean> generate(@Valid @RequestBody List<MaterialPlanBoomDO> list) {
return success(matReqService.generate(list));
return matReqService.generate(list);
}
@GetMapping("/export-excel")
@Operation(summary = "导出领料单主 Excel")

View File

@ -168,4 +168,11 @@ public class StorageLogController {
BeanUtils.toBean(list, StorageLogRespVO.class));
}
@GetMapping("/getSupplementPage")
@Operation(summary = "获得库存补充")
@PreAuthorize("@ss.hasPermission('heli:storage-log:query')")
public CommonResult<PageResult<StorageLogNowDO>> getSupplementPage(@Valid StorageLogPageReqVO pageReqVO) {
PageResult<StorageLogNowDO> pageResult = storageLogService.getSupplementPage(pageReqVO);
return success(pageResult);
}
}

View File

@ -139,24 +139,26 @@ public class MaterialPlanBoomDO extends BaseDO {
private String matUnit;
@TableField(exist = false)
private String matType;
@TableField(exist = false)
private String mplanStatusName;
@TableField(exist = false)
private BigDecimal matRest;
//采购数量
@TableField(exist = false)
private BigDecimal purchaseAmount;
@TableField(exist = false)
//暂估价格
private BigDecimal estimatedPrice;
@TableField(exist = false)
//预估到时间
private LocalDateTime arriveTime;
@TableField(exist = false)
//供应商id
private Long supplierId;
@TableField(exist = false)
//客户简称
private String customerBriefName;
@TableField(exist = false)
private String boomArriveDates;
}

View File

@ -60,6 +60,7 @@ public class StorageLogNowDO extends BaseDO {
private BigDecimal storageOkQtys;
@TableField(exist = false)
private Long matUnitId;
@TableField(exist = false)
private String invSafe;
private String creator;
}

View File

@ -128,19 +128,20 @@ public interface bdgzsomthingMapper extends BaseMapperX<bdgzsomthingDO> {
default PageResult<bdgzsomthingDO> getMessage(bdgzsomthingPageReqVO pageReqVO){
LambdaQueryWrapper<bdgzsomthingDO> query = new LambdaQueryWrapper<>();
query.eq(!StringUtils.isEmpty(pageReqVO.getStatus()),bdgzsomthingDO::getDeleted, pageReqVO.getStatus());
query.eq(bdgzsomthingDO::getDeleted, pageReqVO.getStatus());
query.eq(bdgzsomthingDO::getClick, pageReqVO.getClick());
query.eq(bdgzsomthingDO::getAttr13,"1");
query.isNotNull(bdgzsomthingDO::getAttr6);
Page<bdgzsomthingDO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
Page<bdgzsomthingDO> result = this.selectPage(page, query);
return new PageResult<>(result.getRecords(), result.getTotal());
}
default Long unreadMessage(String name){
LambdaQueryWrapper<bdgzsomthingDO> query = new LambdaQueryWrapper<>();
query.eq(bdgzsomthingDO::getClick, name);
query.isNotNull(bdgzsomthingDO::getAttr6);
query.eq(bdgzsomthingDO::getAttr13,"1");
query.eq(bdgzsomthingDO::getDeleted,0);
return this.selectCount(query);

View File

@ -87,4 +87,9 @@ public interface MaterialMapper extends BaseMapperX<MaterialDO> {
return selectMaps(new QueryWrapper<MaterialDO>().select("id", "name","short_name","code","material_type","spec","unit","brand").eq("virtual_part", YesOrNoEnum.Y.name()).lambda());
}
default List<Map<String, Object>> getbzjList(){
return selectMaps(new QueryWrapper<MaterialDO>().select("id", "name","short_name","code","material_type","spec","unit","brand").eq("material_type", 5));
}
}

View File

@ -166,12 +166,14 @@ public interface MaterialPlanBoomMapper extends BaseMapperX<MaterialPlanBoomDO>
default PageResult<MaterialPlanBoomDO> getStandardPartsPages(MaterialPlanPageReqVO pageReqVO){
MPJLambdaWrapper<MaterialPlanBoomDO> query = new MPJLambdaWrapper<>();
query.selectAll(MaterialPlanBoomDO.class)
.select("p.project_name as projectName","p.project_id as projectId","p.name as projectSubName","mat.material_id as matId")
.select("d.spec as boomSpec","d.blueprint_no as blueprintNo","d.unit as boomUnit")
.select("p.project_name as projectName","p.project_id as projectId","p.name as projectSubName","mat.material_id as matId","m.code as materialName")
.select("d.spec as boomSpec","d.blueprint_no as blueprintNo","d.unit as boomUnit","DATE_FORMAT(t.boom_arrive_date, '%Y-%m-%d') AS boomArriveDates")
.leftJoin(MaterialPlanDO.class, "p", MaterialPlanDO::getId,MaterialPlanBoomDO::getProjectMaterialPlanId)
.leftJoin(ProjectOrderDO.class,"b",ProjectOrderDO::getId,MaterialPlanDO::getProjectId)
.leftJoin(ProcessBomDetailDO.class,"d",ProcessBomDetailDO::getId,MaterialPlanBoomDO::getBoomDetailId)
.leftJoin(MatReqDetailDO.class,"mat",MatReqDetailDO::getProjectMaterialPlanDetailId,MaterialPlanBoomDO::getId)
// .leftJoin(MatReqDetailDO.class,"mat",MatReqDetailDO::getProjectMaterialPlanDetailId,MaterialPlanBoomDO::getId)
.leftJoin("project_mat_req_detail mat on (t.id=mat.project_material_plan_detail_id and mat.deleted=0)")
.leftJoin(MaterialDO.class,"m",MaterialDO::getId,MatReqDetailDO::getMaterialId)
.disableSubLogicDel()
.groupBy(MaterialPlanBoomDO::getId)
.orderByDesc(MaterialPlanBoomDO::getCreateTime);

View File

@ -17,6 +17,7 @@ import org.apache.poi.hpsf.Decimal;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
/**
* /出库日志 Mapper
@ -124,4 +125,82 @@ public interface StorageLogNowMapper extends BaseMapperX<StorageLogNowDO> {
return selectPage(reqVO,query);
}
default PageResult<StorageLogNowDO> getSupplementPage(StorageLogPageReqVO pageReqVO){
// MPJLambdaWrapper<StorageLogNowDO> query = new MPJLambdaWrapper<>()
//// 选择所有字段 + 安全库存字段
// query.selectAll(StorageLogNowDO.class)
// .select("SUM(storage_ok_qty) as storageOkQtys","m.inv_safe as invSafe")
// .select(MaterialDO::getInvSafe) // 添加安全库存字段
// .leftJoin(MaterialDO.class,"m", MaterialDO::getCode, StorageLogNowDO::getMatCode)
// .orderByDesc(StorageLogNowDO::getMatCode);
//
//// 原有条件
// query.like(!StringUtils.isEmpty(pageReqVO.getMatType()), StorageLogNowDO::getMatType, pageReqVO.getMatType())
// .like(!StringUtils.isEmpty(pageReqVO.getMatSpec()), StorageLogNowDO::getMatSpec, pageReqVO.getMatSpec())
// .eq(pageReqVO.getWhId() != null, StorageLogNowDO::getWhId, pageReqVO.getWhId())
// .eq(pageReqVO.getRgId() != null, StorageLogNowDO::getRgId, pageReqVO.getRgId())
// .eq(pageReqVO.getPnId() != null, StorageLogNowDO::getPnId, pageReqVO.getPnId())
// .ne(true, StorageLogNowDO::getStorageOkQty, 0)
// .like(!StringUtils.isEmpty(pageReqVO.getMatName()), StorageLogNowDO::getMatName, pageReqVO.getMatName())
// .like(!StringUtils.isEmpty(pageReqVO.getMatCode()), StorageLogNowDO::getMatCode, pageReqVO.getMatCode())
// .like(!StringUtils.isEmpty(pageReqVO.getLotNo()), StorageLogNowDO::getLotNo, pageReqVO.getLotNo());
//
//// 添加分组和筛选条件
// query.groupBy(StorageLogNowDO::getMatCode)
// .having("SUM(storageOkQtys) < COALESCE(invSafe, 0)");
//
//
// return selectPage(pageReqVO, query);
// 步骤1创建子查询获取符合条件的matCode列表
MPJLambdaWrapper<StorageLogNowDO> subQuery = new MPJLambdaWrapper<>();
subQuery.select(StorageLogNowDO::getMatCode)
.leftJoin(MaterialDO.class, "m", MaterialDO::getCode, StorageLogNowDO::getMatCode)
.groupBy(StorageLogNowDO::getMatCode)
.having("SUM(storage_ok_qty) < COALESCE(MAX(m.inv_safe), 0)");
// .like(!StringUtils.isEmpty(pageReqVO.getMatType()), StorageLogNowDO::getMatType, pageReqVO.getMatType())
// .like(!StringUtils.isEmpty(pageReqVO.getMatSpec()), StorageLogNowDO::getMatSpec, pageReqVO.getMatSpec())
// .eq(pageReqVO.getWhId() != null, StorageLogNowDO::getWhId, pageReqVO.getWhId())
// .eq(pageReqVO.getRgId() != null, StorageLogNowDO::getRgId, pageReqVO.getRgId())
// .eq(pageReqVO.getPnId() != null, StorageLogNowDO::getPnId, pageReqVO.getPnId())
// .ne(true, StorageLogNowDO::getStorageOkQty, 0)
// .like(!StringUtils.isEmpty(pageReqVO.getMatName()), StorageLogNowDO::getMatName, pageReqVO.getMatName())
// .like(!StringUtils.isEmpty(pageReqVO.getMatCode()), StorageLogNowDO::getMatCode, pageReqVO.getMatCode())
// .like(!StringUtils.isEmpty(pageReqVO.getLotNo()), StorageLogNowDO::getLotNo, pageReqVO.getLotNo());
// 执行子查询获取符合条件的matCode
List<String> qualifiedMatCodes = this.selectList(subQuery)
.stream()
.map(StorageLogNowDO::getMatCode)
.distinct()
.collect(Collectors.toList());
// 步骤2主查询返回原始记录
MPJLambdaWrapper<StorageLogNowDO> query = new MPJLambdaWrapper<>();
query.selectAll(StorageLogNowDO.class)
.select("ROUND(m.inv_safe, 2) as invSafe") // 添加安全库存字段
.leftJoin(MaterialDO.class, "m", MaterialDO::getCode, StorageLogNowDO::getMatCode)
.orderByDesc(StorageLogNowDO::getMatCode);
// 复制原有条件
query.like(!StringUtils.isEmpty(pageReqVO.getMatType()), StorageLogNowDO::getMatType, pageReqVO.getMatType())
.like(!StringUtils.isEmpty(pageReqVO.getMatSpec()), StorageLogNowDO::getMatSpec, pageReqVO.getMatSpec())
.eq(pageReqVO.getWhId() != null, StorageLogNowDO::getWhId, pageReqVO.getWhId())
.eq(pageReqVO.getRgId() != null, StorageLogNowDO::getRgId, pageReqVO.getRgId())
.eq(pageReqVO.getPnId() != null, StorageLogNowDO::getPnId, pageReqVO.getPnId())
.ne(true, StorageLogNowDO::getStorageOkQty, 0)
.like(!StringUtils.isEmpty(pageReqVO.getMatName()), StorageLogNowDO::getMatName, pageReqVO.getMatName())
.like(!StringUtils.isEmpty(pageReqVO.getMatCode()), StorageLogNowDO::getMatCode, pageReqVO.getMatCode())
.like(!StringUtils.isEmpty(pageReqVO.getLotNo()), StorageLogNowDO::getLotNo, pageReqVO.getLotNo())
.isNotNull(MaterialDO::getInvSafe);
// 添加筛选条件只返回符合条件的matCode组中的记录
if (!qualifiedMatCodes.isEmpty()) {
query.in(StorageLogNowDO::getMatCode, qualifiedMatCodes);
} else {
// 如果没有符合条件的matCode返回空结果
query.apply("1 = 0");
}
return selectPage(pageReqVO, query);
}
}

View File

@ -58,4 +58,6 @@ public interface MaterialService {
List<Map<String, Object>> selectSimpleVirtualList();
void importExcel(List<MaterialExcelVO> materialExcelVOList, Boolean updateSupport);
List<Map<String, Object>> getbzjList();
}

View File

@ -204,6 +204,10 @@ public class MaterialServiceImpl implements MaterialService {
}));
}
@Override
public List<Map<String, Object>> getbzjList() {
return materialMapper.getbzjList(); }
private void checkData(List<MaterialExcelVO> materialExcelVOList) {
// 基础校验
Set<ConstraintViolation<List<MaterialExcelVO>>> validate = validator.validate(materialExcelVOList, MaterialExcelVO.class);

View File

@ -11,6 +11,7 @@ import com.chanko.yunxi.mes.framework.common.pojo.PageResult;
import com.chanko.yunxi.mes.framework.common.pojo.PageParam;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.materialplanboom.MaterialPlanBoomDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.processbom.ProcessBomDetailDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogNow.StorageLogNowDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.taskdispatch.TaskDispatchDetailDO;
/**
@ -75,4 +76,6 @@ public interface MaterialPlanService {
PageResult<MaterialPlanBoomDO> getStandardPartsPages(MaterialPlanPageReqVO pageReqVO);
CommonResult<Boolean> operation(MaterialPlanPageReqVO pageReqVO);
Boolean supplement(List<StorageLogNowDO> list);
}

View File

@ -8,11 +8,14 @@ import com.chanko.yunxi.mes.framework.common.util.object.ObjectUtils;
import com.chanko.yunxi.mes.framework.security.core.util.SecurityFrameworkUtils;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.attentiontodo.AttentiontodoDO;
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.materialplanboom.MaterialPlanBoomDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.processbom.ProcessBomDetailDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.serialnumber.SerialNumberDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogNow.StorageLogNowDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.taskdispatch.TaskDispatchDetailDO;
import com.chanko.yunxi.mes.module.heli.dal.mysql.attentiontodo.AttentiontodoMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.material.MaterialMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.materialplanboom.MaterialPlanBoomMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.processbom.ProcessBomDetailMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.taskdispatch.TaskDispatchDetailMapper;
@ -77,6 +80,8 @@ public class MaterialPlanServiceImpl implements MaterialPlanService {
private ProcessBomDetailMapper processBomDetailMapper;
@Resource
private TaskDispatchDetailMapper taskDispatchDetailMapper;
@Resource
private MaterialMapper materialMapper;
@Override
public Long createMaterialPlan(MaterialPlanSaveReqVO createReqVO) {
// 插入
@ -371,4 +376,35 @@ public class MaterialPlanServiceImpl implements MaterialPlanService {
return CommonResult.success(true);
}
@Override
public Boolean supplement(List<StorageLogNowDO> list) {
MaterialPlanDO planDO = new MaterialPlanDO();
SerialNumberDO serialNumberDO = new SerialNumberDO();
serialNumberDO = serialNumberService.getSerialNumber(MATERIAL_PLAN.name(), new SimpleDateFormat("yyyyMMdd").format(new Date()));
serialNumberDO.setSerialNumber(serialNumberDO.getSerialNumber()+1);
planDO.setProjectMaterialPlanNo(MATERIAL_PLAN.getCode(serialNumberDO.getSerialNumber().toString()));
planDO.setMatType(2);
planDO.setMatPlanDate(new Date());
materialPlanMapper.insert(planDO);
// 回写序列记录
serialNumberService.updateSerialNumber(serialNumberDO);
List<MaterialPlanBoomDO> materialPlanBoomDOList = new ArrayList<>();
for (StorageLogNowDO nowDO : list) {
MaterialPlanBoomDO boomDO = new MaterialPlanBoomDO();
boomDO.setProjectMaterialPlanId(planDO.getId());
boomDO.setBoomAmount(nowDO.getStorageOkQtys());
boomDO.setMplanStatus(0);
LambdaQueryWrapper<MaterialDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MaterialDO::getCode, nowDO.getMatCode());
MaterialDO materialDO = materialMapper.selectOne(queryWrapper);
if (ObjectUtil.isNotEmpty(materialDO)){
boomDO.setMatName(materialDO.getName());
boomDO.setMaterialId(materialDO.getId());
}
materialPlanBoomDOList.add(boomDO);
}
materialPlanBoomMapper.insertOrUpdateBatch(materialPlanBoomDOList);
return true;
}
}

View File

@ -2,6 +2,8 @@ package com.chanko.yunxi.mes.module.heli.service.matreq;
import java.util.*;
import javax.validation.*;
import com.chanko.yunxi.mes.framework.common.pojo.CommonResult;
import com.chanko.yunxi.mes.module.heli.controller.admin.matreq.vo.*;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.materialplanboom.MaterialPlanBoomDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.matreq.MatReqDO;
@ -53,5 +55,5 @@ public interface MatReqService {
*/
PageResult<MatReqDO> getMatReqPage(MatReqPageReqVO pageReqVO);
Boolean generate(List<MaterialPlanBoomDO> list);
CommonResult<Boolean> generate(List<MaterialPlanBoomDO> list);
}

View File

@ -1,16 +1,26 @@
package com.chanko.yunxi.mes.module.heli.service.matreq;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.chanko.yunxi.mes.framework.common.pojo.CommonResult;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.material.MaterialDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.materialplan.MaterialPlanDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.materialplanboom.MaterialPlanBoomDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.matreqdetail.MatReqDetailDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.serialnumber.SerialNumberDO;
import com.chanko.yunxi.mes.module.heli.dal.mysql.material.MaterialMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.materialplan.MaterialPlanMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.materialplanboom.MaterialPlanBoomMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.matreqdetail.MatReqDetailMapper;
import com.chanko.yunxi.mes.module.heli.service.serialnumber.SerialNumberService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
@ -23,6 +33,8 @@ import com.chanko.yunxi.mes.framework.common.util.object.BeanUtils;
import com.chanko.yunxi.mes.module.heli.dal.mysql.matreq.MatReqMapper;
import static com.chanko.yunxi.mes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.chanko.yunxi.mes.module.heli.enums.CodeEnum.MAT_REQ;
import static com.chanko.yunxi.mes.module.heli.enums.CodeEnum.PURCHASE_ORDER;
import static com.chanko.yunxi.mes.module.heli.enums.ErrorCodeConstants.*;
/**
@ -39,7 +51,13 @@ public class MatReqServiceImpl implements MatReqService {
@Resource
private MaterialPlanBoomMapper materialPlanBoomMapper;
@Resource
private MaterialPlanMapper materialPlanMapper;
@Resource
private MatReqDetailMapper matReqDetailMapper;
@Resource
private SerialNumberService serialNumberService;
@Resource
private MaterialMapper materialMapper;
@Override
public Long createMatReq(MatReqSaveReqVO createReqVO) {
@ -98,9 +116,59 @@ public class MatReqServiceImpl implements MatReqService {
}
@Override
public Boolean generate(List<MaterialPlanBoomDO> list) {
return null;
public CommonResult<Boolean> generate(List<MaterialPlanBoomDO> list) {
List<Long> ids = list.stream()
.map(MaterialPlanBoomDO::getId)
.collect(Collectors.toList());
LambdaQueryWrapper<MaterialPlanBoomDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(MaterialPlanBoomDO::getId,ids);
queryWrapper.ne(MaterialPlanBoomDO::getIsPurYard,1);
List<MaterialPlanBoomDO> materialPlanBoomDOS = materialPlanBoomMapper.selectList(queryWrapper);
if (ObjectUtil.isNotEmpty(materialPlanBoomDOS)) return CommonResult.error(400,"该物料信息状态非库存状态,请刷新界面!");
MatReqDO matReqDO = new MatReqDO();
SerialNumberDO serialNumberDO = new SerialNumberDO();
serialNumberDO = serialNumberService.getSerialNumber(MAT_REQ.name(), new SimpleDateFormat("yyyyMMdd").format(new Date()));
serialNumberDO.setSerialNumber(serialNumberDO.getSerialNumber()+1);
// 回写序列记录
serialNumberService.updateSerialNumber(serialNumberDO);
matReqDO.setMatReqNo(MAT_REQ.getCode(serialNumberDO.getSerialNumber().toString()));
matReqDO.setGoodsType(1);
matReqDO.setStatus(0);
MaterialPlanDO planDO = materialPlanMapper.selectById(list.get(0).getProjectMaterialPlanId());
matReqDO.setProjectId(planDO.getProjectId());
matReqDO.setProjectName(planDO.getProjectName());
matReqDO.setCustomerId(planDO.getCustomerId());
matReqDO.setReqDate(LocalDate.now());
matReqMapper.insert(matReqDO);
List<MatReqDetailDO> matReqDetailDOS = new ArrayList<>();
for (MaterialPlanBoomDO materialPlanBoomDO : list) {
MaterialPlanBoomDO boomDO = materialPlanBoomMapper.selectById(materialPlanBoomDO.getId());
if (ObjectUtil.isNotEmpty(boomDO)){
MaterialPlanDO plan = materialPlanMapper.selectById(boomDO.getProjectMaterialPlanId());
MatReqDetailDO matReqDetailDO = new MatReqDetailDO();
matReqDetailDO.setMatReqId(matReqDO.getId());
matReqDetailDO.setBoomDetailId(boomDO.getBoomDetailId());
MaterialDO materialDO = materialMapper.selectById(materialPlanBoomDO.getMatId());
if (ObjectUtil.isNotEmpty(materialDO)){
matReqDetailDO.setBoomName(materialDO.getName());
matReqDetailDO.setBoomSpec(materialDO.getSpec());
matReqDetailDO.setBoomUnit(materialDO.getUnit());
}
matReqDetailDO.setBoomAmount(boomDO.getBoomAmount());
matReqDetailDO.setRequireTime(boomDO.getBoomArriveDate());
matReqDetailDO.setProjectPlanSubId(plan.getProjectPlanSubId());
matReqDetailDO.setName(plan.getName());
matReqDetailDO.setNameSim(plan.getNameSim());
matReqDetailDO.setMaterialId(materialPlanBoomDO.getMatId());
matReqDetailDO.setProjectMaterialPlanDetailId(boomDO.getId());
matReqDetailDO.setProjectMaterialPlanId(boomDO.getProjectMaterialPlanId());
matReqDetailDOS.add(matReqDetailDO);
boomDO.setIsPurYard(3);
materialPlanBoomMapper.updateById(boomDO);
}
}
matReqDetailMapper.insertOrUpdateBatch(matReqDetailDOS);
return CommonResult.success(true);
}
}

View File

@ -394,6 +394,7 @@ public class ProcessDesignServiceImpl implements ProcessDesignService {
BdgzsomthingDO.setAttr7(processDesignDO.getProjectName());
BdgzsomthingDO.setAttr8(processDesignDO.getProjectSubName());
BdgzsomthingDO.setAttr9(processDesignProgressDO.getRemark());
BdgzsomthingDO.setAttr13("1");
bdgzsomthingMapper.insert(BdgzsomthingDO);
}
}

View File

@ -74,4 +74,6 @@ public interface StorageLogService {
PageResult<StorageLogNowDO> getStorageNowPricePage(StorageLogPageReqVO pageReqVO);
void updatePrice(StorageLogSaveReqVO updateReqVO);
PageResult<StorageLogNowDO> getSupplementPage(StorageLogPageReqVO pageReqVO);
}

View File

@ -214,4 +214,8 @@ public class StorageLogServiceImpl implements StorageLogService {
materialMapper.update(wrapper);
}
@Override
public PageResult<StorageLogNowDO> getSupplementPage(StorageLogPageReqVO pageReqVO) {
return storageLogNowMapper.getSupplementPage(pageReqVO); }
}

View File

@ -67,3 +67,6 @@ export const deleteMaterial = async (id: number) => {
export const exportMaterial = async (params) => {
return await request.download({ url: `/heli/material/export-excel`, params })
}
export const getbzjList = async () => {
return await request.get({ url: `/heli/material/getbzjList` })
}

View File

@ -82,3 +82,11 @@ export const getStandardPartsPages = async (params) => {
export const operation = async (params) => {
return await request.get({ url: `/heli/material-plan/operation`, params })
}
// 导出物料需求计划 Excel
export const exportStandardParts = async (params) => {
return await request.download({ url: `/heli/material-plan/exportStandardParts`, params })
}
export const supplement = async (data) => {
return await request.post({ url: `/heli/material-plan/supplement`, data })
}

View File

@ -85,3 +85,8 @@ export const deleteStorageLog = async (id: number) => {
export const exportStorageLog = async (params) => {
return await request.download({ url: `/heli/storage-log/export-excel`, params })
}
// 查询入/出库实时分页
export const getSupplementPage = async (params) => {
return await request.get({ url: `/heli/storage-log/getSupplementPage`, params })
}

View File

@ -0,0 +1,121 @@
<template>
<!-- 物料选择 -->
<el-select v-model="valueName" v-if="status1==false" placeholder="请输入物料" :remote-method="remoteMethod" remote-show-suffix remote clearable reserve-keyword filterable :loading="Loading" @change="onSelectChange" @visible-change="onVisibleChange">
<el-option v-for="item in materialSelectList" :key="item.id" :label="item.code+' '+item.name" :value="item.id" />
</el-select>
<el-select v-model="valueName" v-else style="text-decoration: line-through" placeholder="请输入物料" :remote-method="remoteMethod" remote-show-suffix remote clearable reserve-keyword filterable :loading="Loading" @change="onSelectChange" @visible-change="onVisibleChange">
<el-option v-for="item in materialSelectList" :key="item.id" :label="item.code+' '+item.name" :value="item.id" />
</el-select>
</template>
<script lang="ts" setup>
import { ref, onMounted, toRefs } from 'vue'
import * as MaterialApi from '@/api/heli/material'
import {getSimpList, getSimpVirtualList} from "@/api/heli/material";
const valueName: any = ref() //
const valueNameObject: any = ref() //
const emit = defineEmits(['update:newValue'])
const materialList = ref<MaterialApi.MaterialVO[]>([]) //
const materialSelectList = ref<MaterialApi.MaterialVO[]>([])
const Loading = ref(false)
const materialSelectLoading = ref(false)
const props = defineProps({
modelValue: {
type: [Number, String],
required: true // true
}
})
const propsmodelValue = toRefs(props).modelValue // props modelValue
const initialValue: any = ref(null) // ID
const queryParams = {
pageNo: 1,
pageSize: 10,
code: undefined,
brief: undefined,
virtualPart: 'N',
status: 1,
codeAndName: undefined
}
const status1 = ref(false)
const gitlist = async () => {
const data = await MaterialApi.getbzjList()
materialList.value = []
materialSelectList.value = []
materialList.value = [...materialList.value, ...data]
console.log(propsmodelValue.value)
//
if (propsmodelValue.value) {
valueName.value = propsmodelValue.value
const initialmaterial = await MaterialApi.getMaterial(valueName.value)
if (initialmaterial.status == 2) {
status1.value = true
} else {
status1.value = false
}
// materialList
let foundInitialmaterialInList = false
for (const material of materialList.value) {
if (material.id === initialmaterial.id) {
foundInitialmaterialInList = true
break
}
}
//
if (!foundInitialmaterialInList) {
materialList.value.unshift(initialmaterial)
}
}
materialSelectList.value = materialList.value
Loading.value = false
}
const remoteMethod = async (query: any) => {
materialSelectLoading.value = true
materialSelectList.value = []
try {
if (query) {
queryParams.codeAndName = query
const data = await MaterialApi.getMaterialPage(queryParams)
materialList.value = data.list
materialSelectList.value = data.list
} else {
gitlist()
}
} catch (error) {
console.error(error)
} finally {
materialSelectLoading.value = false
}
}
//
onMounted(async () => {
try {
await gitlist()
} catch (error) {
console.error(error)
}
})
watch(valueName, (newValue: any) => {
if (newValue) {
materialList.value = []
gitlist()
}
})
const onVisibleChange = (isVisible: boolean) => {
if (!isVisible) {
//
queryParams.codeAndName = undefined
materialList.value = []
materialSelectList.value = []
} else {
gitlist()
}
}
const onSelectChange = (newValue: any) => {
valueNameObject.value = materialList.value.find((material) => material.id === newValue) //
emit('update:newValue', valueNameObject.value)
}
</script>

View File

@ -64,8 +64,11 @@
<template #header><span class="hl-table_header">*</span>物料编码</template>
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.matId`" class="mb-0px!" >
<!-- <UserSelect v-model="row.materialId" class="!w-265px" clearable @update:newValue="handleSelected($index, $event)"/>-->
<MaterialSelect v-model="row.matId" @update:newValue="handleSelected($index, $event)" clearable/>
<el-select v-model="row.matId" placeholder="请输入物料" clearable filterable >
<el-option v-for="item in materialSelectList" :key="item.id" :label="item.code+' '+item.name" :value="item.id" />
</el-select>
<!-- <MaterialSelect v-model="row.matId" @update:newValue="handleSelected($index, $event)" clearable/>-->
</el-form-item>
</template>
</el-table-column>
@ -84,9 +87,9 @@
<el-table-column label="要求完成日期" align="center" prop="boomArriveDate" min-width="150" :formatter="dateFormatter1" />
<el-table-column label="操作" align="center" fixed="right" min-width="280">
<template #default="scope">
<!-- <el-button link type="primary" @click="operation('queren', scope.row.id)" v-if="scope.row.isPurYard==1">-->
<!-- 确认-->
<!-- </el-button>-->
<el-button link type="primary" @click="operation('queren', scope.row.id)" v-if="scope.row.isPurYard==1">
确认
</el-button>
<el-button link type="primary" @click="operation('bucong', scope.row.id)" v-if="scope.row.isPurYard==1">
库存补充
</el-button>
@ -129,12 +132,13 @@ const message = useMessage() // 消息弹窗
const { t } = useI18n() //
import download from '@/utils/download'
import UserSelect from "@/views/heli/materialplan/userSelectNew.vue";
import MaterialSelect from "@/views/heli/hlvuestyle/materialSelect.vue";
import MaterialSelect from "@/views/heli/matreq/materialNewSelect.vue";
import {ref} from "vue";
import {ElTable} from "element-plus";
import {getStandardPartsPages} from "@/api/heli/materialplan";
import * as MatReqApi from "@/api/heli/matreq";
import {generate} from "@/api/heli/matreq";
import * as MaterialApi from "@/api/heli/material";
const loading = ref(true) //
const list = ref([]) //
const total = ref(0) //
@ -159,6 +163,7 @@ const queryParams = reactive({
type:undefined,
projectCode:undefined
})
const materialSelectList = ref([])
const queryFormRef = ref() //
const exportLoading = ref(false) //
const multipleTable = ref<InstanceType<typeof ElTable>>()
@ -208,7 +213,7 @@ const submitForm = async () => {
}
// 4. Element Plus
formLoading.value = true;
const data = await MatReqApi.getMatReqPage(queryParams)
// const data = await MatReqApi.getMatReqPage(queryParams)
// 5.
const res = await Promise.race([
@ -275,8 +280,8 @@ const handleExportDetail = async () => {
await message.exportConfirm()
//
exportLoading.value = true
const data = await MaterialPlanApi.exportStandard(queryParams)
download.excel(data, '标准件物料需求计划.xlsx')
const data = await MaterialPlanApi.exportStandardParts(queryParams)
download.excel(data, '标准件库存.xlsx')
} catch {
} finally {
exportLoading.value = false
@ -300,7 +305,7 @@ const userInit = ref()
/** 初始化 **/
onMounted(async () => {
//
// userInit.value = await UserApi.getSimpleUserList()
materialSelectList.value = await MaterialApi.getbzjList() ;
getList()
})
</script>

View File

@ -0,0 +1,275 @@
<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="matName">
<el-input
v-model="queryParams.matName" placeholder="物料名称" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<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="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 label="仓库" prop="whId">-->
<!-- <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 label="库区" prop="rgId">
<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 label="库位" prop="pnId">
<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 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-button type="warning" size="mini" @click="printfClick">-->
<!-- <Icon icon="ep:printer" class="mr-5px"/>-->
<!-- 打印</el-button>-->
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<el-card class="hl-card-info">
<template #header>
<div class="hl-card-info-icona"></div><span class="hl-card-info-text">库存明细</span>
<el-button style="margin-left: 20px" @click="supplement()" type="primary" size="large">库存补充</el-button>
</template>
<el-row>
<el-col>
<el-card class="hl-incard">
<el-form ref="multipleTable" :model="list" v-loading="formLoading" label-width="0" >
<el-table v-loading="loading" :data="list" :stripe="true" @selection-change="handleSelectionChange" :show-overflow-tooltip="true" class="hl-table">
<el-table-column
type="selection"
width="55"/>
<el-table-column type="index" width="100" fixed label="序号" align="center" />
<el-table-column label="物料编码" align="center" prop="matCode" fixed min-width="120" />
<el-table-column label="物料名称" align="center" prop="matName" fixed min-width="120"/>
<el-table-column label="规格型号" align="center" prop="matSpec" min-width="120"/>
<el-table-column label="仓库" align="center" prop="whName" min-width="120"/>
<el-table-column label="库区" align="center" prop="rgName" min-width="120"/>
<el-table-column label="库位" align="center" prop="pnName" min-width="120"/>
<el-table-column label="库存数量" align="center" prop="storageOkQty" min-width="100"/>
<el-table-column label="安全库存" align="center" prop="invSafe" min-width="100"/>
<el-table-column label="系统单位" align="center" prop="matUnit" min-width="100"/>
<el-table-column min-width="200px" align="center" fixed="right">
<template #header><span class="hl-table_header">*</span>补充数量</template>
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.storageOkQtys`" class="mb-0px!" style="margin-left:10px ">
<el-input-number v-model="row.storageOkQtys" type="number" :precision="2" />
</el-form-item>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</el-form>
</el-card>
</el-col>
</el-row>
</el-card>
</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 printDialog from './printDialog.vue'
import * as MatReqApi from "@/api/heli/matreq";
import {ref} from "vue";
import {ElTable} from "element-plus";
import * as MaterialPlanApi from "@/api/heli/materialplan";
defineOptions({ name: 'StorageLog' })
const printref = ref()
const whList = ref([])
const rgList = ref([])
const pnList = ref([])
const formLoading = ref(false) // 12
const rgCurrentList = ref([])
const pnCurrentList = ref([])
const message = useMessage() //
const { t } = useI18n() //
const multipleTable = ref<InstanceType<typeof ElTable>>()
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 getList = async () => {
loading.value = true
try {
const data = await StorageLogApi.getSupplementPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
const handleSelectionChange = (val) => {
multipleTable.value = val;
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
const supplement = async () => {
try {
const list = multipleTable.value|| []; //
// 1.
if (!list || list.length==null) {
message.error("提交明细不能为空,请确认");
return;
}
// 使 Set matCode
const seenMatCodes = new Set();
for (let i = 0; i < list.length; i++) {
const item = list[i];
// 2.
if (!item.matCode) {
message.error(`物料 ${item.matCode} 的物料编码为空,请确认`);
return;
}
if (!item.storageOkQtys) {
message.error(`物料 ${item.matCode} 的补充数量为空,请确认`);
return;
}
// 3.
if (seenMatCodes.has(item.matCode)) {
message.error(`该物料编码 ${item.matCode} 存在多条数据,请确认`);
return;
}
//
seenMatCodes.add(item.matCode);
}
// 5.
const res = await Promise.race([
MaterialPlanApi.supplement(list),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("请求超时")), 30000)
)
]);
// 4. Element Plus
formLoading.value = true;
message.success("补充成功");
getList(); //
emit('success');
} catch (error) {
console.error("提交失败:", error);
// message.error(`: ${error.message || ""}`);
} finally {
formLoading.value = false;
}
}
const handleWh = async (wid) => {
queryParams.rgId = undefined
queryParams.pnId = undefined
rgCurrentList.value =[]
pnCurrentList.value =[]
rgCurrentList.value = rgList.value
}
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 handleQuery()
queryParams.rgId = undefined
queryParams.pnId = undefined
rgCurrentList.value =[]
pnCurrentList.value =[]
rgCurrentList.value = rgList.value
})
</script>

View File

@ -7,7 +7,7 @@
* @Description: ,`customMade`, koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// export const serviceDomain = 'https://nxhs.cjyx.cc'
export const serviceDomain = 'https://star.hz-hl.com'
// export const serviceDomain = 'https://star.hz-hl.com'
// export const serviceDomain = 'http://222.71.165.187:9010'
//export const serviceDomain = 'http://localhost:8080'
export const serviceDomain = 'http://localhost:8080'
// export const serviceDomain = 'https://nxhs.cjyx.cc'