Merge remote-tracking branch 'origin/main'

main
liutao 13 hours ago
commit 4426ae0b55

@ -25,6 +25,7 @@ import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
@ -84,7 +85,10 @@ public class ErpPalletController {
PageResult<ErpPalletDO> pageResult = palletService.getPalletPage(pageReqVO);
Map<Long, String> qrcodeMap = qrcodeService.selectQrcodeUrlMapByBizTypeAndIds(QrcodeBizTypeEnum.PALLET.getCode(),
convertList(pageResult.getList(), ErpPalletDO::getId));
List<ErpPalletRespVO> list = convertList(pageResult.getList(), pallet -> buildPalletRespVO(pallet, qrcodeMap));
Map<Long, BigDecimal> lockedPackageCountMap = palletService.getLockedPackageCountMap(
convertList(pageResult.getList(), ErpPalletDO::getId));
List<ErpPalletRespVO> list = convertList(pageResult.getList(),
pallet -> buildPalletRespVO(pallet, qrcodeMap, lockedPackageCountMap));
return success(new PageResult<>(list, pageResult.getTotal()));
}
@ -98,7 +102,10 @@ public class ErpPalletController {
PageResult<ErpPalletDO> pageResult = palletService.getPalletPage(pageReqVO);
Map<Long, String> qrcodeMap = qrcodeService.selectQrcodeUrlMapByBizTypeAndIds(QrcodeBizTypeEnum.PALLET.getCode(),
convertList(pageResult.getList(), ErpPalletDO::getId));
List<ErpPalletRespVO> list = convertList(pageResult.getList(), pallet -> buildPalletRespVO(pallet, qrcodeMap));
Map<Long, BigDecimal> lockedPackageCountMap = palletService.getLockedPackageCountMap(
convertList(pageResult.getList(), ErpPalletDO::getId));
List<ErpPalletRespVO> list = convertList(pageResult.getList(),
pallet -> buildPalletRespVO(pallet, qrcodeMap, lockedPackageCountMap));
ExcelUtils.write(response, "托盘.xls", "数据", ErpPalletRespVO.class, list);
}
@ -151,6 +158,13 @@ public class ErpPalletController {
return respVO;
}
private ErpPalletRespVO buildPalletRespVO(ErpPalletDO pallet, Map<Long, String> qrcodeMap,
Map<Long, BigDecimal> lockedPackageCountMap) {
ErpPalletRespVO respVO = buildPalletRespVO(pallet, qrcodeMap);
respVO.setLockedPackageCount(lockedPackageCountMap.getOrDefault(pallet.getId(), BigDecimal.ZERO));
return respVO;
}
private void fillPackagingInfo(ErpPalletRespVO respVO) {
if (respVO == null) {
return;

@ -69,6 +69,9 @@ public class ErpPalletRespVO {
@Schema(description = "当前包数", example = "20")
private BigDecimal packageCount;
@Schema(description = "锁定包数", example = "5")
private BigDecimal lockedPackageCount;
@Schema(description = "二维码", example = "https://xxx.com/qrcode/pallet/1")
@ExcelProperty("二维码")
private String qrcode;

@ -70,8 +70,7 @@ public class ErpProductCategoryController {
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('erp:product-category:query')")
public CommonResult<ErpProductCategoryRespVO> getProductCategory(@RequestParam("id") Long id) {
ErpProductCategoryDO category = productCategoryService.getProductCategory(id);
return success(BeanUtils.toBean(category, ErpProductCategoryRespVO.class));
return success(productCategoryService.getProductCategoryResp(id));
}
@GetMapping("/list")

@ -110,6 +110,14 @@ public class ErpProductController {
return success(productService.getProduct(id, code));
}
@GetMapping("/get-process-route")
@Operation(summary = "获得产品对应的工艺路线快照")
@Parameter(name = "productId", description = "产品编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('erp:product:query')")
public CommonResult<ErpProductProcessRouteRespVO> getProductProcessRoute(@RequestParam("productId") Long productId) {
return success(productService.getProductProcessRoute(productId));
}
@GetMapping("/page")
@Operation(summary = "获得产品分页")
@PreAuthorize("@ss.hasPermission('erp:product:query')")

@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - ERP 产品分类工艺路线明细快照 Response VO")
@Data
public class ErpProductCategoryProcessRouteItemRespVO {
@Schema(description = "编号", example = "1")
private Long id;
@Schema(description = "产品分类编号", example = "1")
private Long categoryId;
@Schema(description = "工艺路线编号", example = "1")
private Long processRouteId;
@Schema(description = "工艺路线明细编号", example = "1")
private Long processRouteItemId;
@Schema(description = "排序,从 1 开始", example = "1")
private Integer sort;
@Schema(description = "工艺参数编号", example = "100")
private Long processParameterId;
@Schema(description = "工艺参数编码")
private String processParameterCode;
@Schema(description = "工艺参数名称")
private String processParameterName;
@Schema(description = "备注")
private String remark;
}

@ -11,6 +11,7 @@ import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.PRODUCT_CATEGO
import static cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - ERP 产品分类 Response VO")
@Data
@ -51,4 +52,13 @@ public class ErpProductCategoryRespVO {
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "工艺路线 ID对应 /mes/process-route", example = "1")
private Long processRouteId;
@Schema(description = "工艺路线名称")
private String processRouteName;
@Schema(description = "工艺路线明细快照")
private List<ErpProductCategoryProcessRouteItemRespVO> processRouteItems;
}

@ -37,4 +37,7 @@ public class ErpProductCategorySaveReqVO {
@NotNull(message = "开启状态不能为空")
private Integer status;
@Schema(description = "工艺路线 ID对应 /mes/process-route", example = "1")
private Long processRouteId;
}

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryProcessRouteItemRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - ERP 产品工艺路线快照 Response VO")
@Data
public class ErpProductProcessRouteRespVO {
@Schema(description = "产品编号", example = "1")
private Long productId;
@Schema(description = "工艺路线 ID对应 /mes/process-route", example = "1")
private Long processRouteId;
@Schema(description = "工艺路线名称")
private String processRouteName;
@Schema(description = "工艺路线明细快照")
private List<ErpProductCategoryProcessRouteItemRespVO> processRouteItems;
}

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryProcessRouteItemRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
@ -162,4 +163,13 @@ public class ErpProductRespVO extends ErpProductDO {
@Schema(description = "默认供应商 ID", example = "1")
private Long defaultSupplierId;
@Schema(description = "产品分类关联的工艺路线 ID对应 /mes/process-route", example = "1")
private Long processRouteId;
@Schema(description = "产品分类关联的工艺路线名称")
private String processRouteName;
@Schema(description = "产品分类保存的工艺路线明细快照")
private List<ErpProductCategoryProcessRouteItemRespVO> processRouteItems;
}

@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemMapper;
import cn.iocoder.yudao.module.erp.service.pallet.ErpPalletService;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService;
@ -70,6 +71,10 @@ public class ErpStockController {
private ErpStockRecordService stockRecordService;
@Resource
private ErpPalletService palletService;
@Resource
private ErpStockOutItemMapper stockOutItemMapper;
private static final List<Integer> LOCKED_STOCK_OUT_STATUSES = java.util.Arrays.asList(10, 0, 1);
@GetMapping("/get")
@Operation(summary = "获得产品库存")
@ -174,6 +179,8 @@ public class ErpStockController {
fillPackagingSnapshot(respVO, product);
}
fillDerivedFields(respVO);
respVO.setLockedStockCount(stockOutItemMapper.selectLockedStockCount(
respVO.getProductId(), respVO.getWarehouseId(), respVO.getAreaId(), LOCKED_STOCK_OUT_STATUSES));
respVO.setPalletCount(getPalletCount(respVO));
respVO.setPackagingRule(buildPackagingRule(respVO));
respVO.setStockDisplay(buildStockDisplay(respVO));

@ -39,6 +39,9 @@ public class ErpStockRespVO {
@ExcelProperty("库存数量")
private BigDecimal count;
@Schema(description = "锁定库存数量", example = "10")
private BigDecimal lockedStockCount;
@Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11161")
private Long categoryId;

@ -57,4 +57,13 @@ public class ErpProductCategoryDO extends BaseDO {
*/
private Integer status;
/**
* 线 ID
*/
private Long processRouteId;
/**
* 线
*/
private String processRouteName;
}

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.erp.dal.dataobject.product;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* ERP 线 DO
*/
@TableName("erp_product_category_process_route_item")
@KeySequence("erp_product_category_process_route_item_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ErpProductCategoryProcessRouteItemDO extends BaseDO {
@TableId
private Long id;
private Long categoryId;
private Long processRouteId;
private Long processRouteItemId;
private Integer sort;
private Long processParameterId;
private String processParameterCode;
private String processParameterName;
private String remark;
}

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.erp.dal.mysql.pallet;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.erp.controller.admin.pallet.enums.ErpPalletStatusEnum;
import cn.iocoder.yudao.module.erp.controller.admin.pallet.vo.ErpPalletPageReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO;
import org.apache.ibatis.annotations.Mapper;
@ -16,19 +17,29 @@ import java.util.List;
public interface ErpPalletMapper extends BaseMapperX<ErpPalletDO> {
default PageResult<ErpPalletDO> selectPage(ErpPalletPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ErpPalletDO>()
LambdaQueryWrapperX<ErpPalletDO> query = new LambdaQueryWrapperX<ErpPalletDO>()
.likeIfPresent(ErpPalletDO::getCode, reqVO.getCode())
.eqIfPresent(ErpPalletDO::getPalletType, reqVO.getPalletType())
.eqIfPresent(ErpPalletDO::getStatus, reqVO.getStatus())
.neIfPresent(ErpPalletDO::getStatus, reqVO.getExcludeStatus())
.eqIfPresent(ErpPalletDO::getWarehouseId, reqVO.getWarehouseId())
.eqIfPresent(ErpPalletDO::getAreaId, reqVO.getAreaId())
.likeIfPresent(ErpPalletDO::getPlanCode, reqVO.getPlanCode())
.eqIfPresent(ErpPalletDO::getProductId, reqVO.getProductId())
.betweenIfPresent(ErpPalletDO::getPurchaseDate, reqVO.getPurchaseDate())
.betweenIfPresent(ErpPalletDO::getUseDate, reqVO.getUseDate())
.betweenIfPresent(ErpPalletDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(ErpPalletDO::getId));
.orderByDesc(ErpPalletDO::getId);
if (reqVO.getProductId() != null && reqVO.getExcludeStatus() != null && reqVO.getStatus() == null) {
query.and(wrapper -> wrapper
.and(productWrapper -> productWrapper
.eq(ErpPalletDO::getProductId, reqVO.getProductId())
.ne(ErpPalletDO::getStatus, reqVO.getExcludeStatus()))
.or()
.eq(ErpPalletDO::getStatus, ErpPalletStatusEnum.IDLE.getStatus()));
} else {
query.eqIfPresent(ErpPalletDO::getStatus, reqVO.getStatus())
.neIfPresent(ErpPalletDO::getStatus, reqVO.getExcludeStatus())
.eqIfPresent(ErpPalletDO::getProductId, reqVO.getProductId());
}
return selectPage(reqVO, query);
}
default ErpPalletDO selectByCode(String code) {

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.erp.dal.mysql.product;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryProcessRouteItemDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ErpProductCategoryProcessRouteItemMapper extends BaseMapperX<ErpProductCategoryProcessRouteItemDO> {
default List<ErpProductCategoryProcessRouteItemDO> selectListByCategoryId(Long categoryId) {
return selectList(new LambdaQueryWrapperX<ErpProductCategoryProcessRouteItemDO>()
.eq(ErpProductCategoryProcessRouteItemDO::getCategoryId, categoryId)
.orderByAsc(ErpProductCategoryProcessRouteItemDO::getSort)
.orderByAsc(ErpProductCategoryProcessRouteItemDO::getId));
}
default void deleteByCategoryId(Long categoryId) {
delete(new LambdaQueryWrapperX<ErpProductCategoryProcessRouteItemDO>()
.eq(ErpProductCategoryProcessRouteItemDO::getCategoryId, categoryId));
}
}

@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
@ -85,11 +86,27 @@ public interface ErpStockMapper extends BaseMapperX<ErpStockDO> {
}
default ErpStockDO selectByProductIdAndWarehouseIdAndAreaId(Long productId, Long warehouseId, Long areaId) {
return selectOne(new LambdaQueryWrapperX<ErpStockDO>()
if (areaId != null) {
return selectOne(new LambdaQueryWrapperX<ErpStockDO>()
.eq(ErpStockDO::getProductId, productId)
.eq(ErpStockDO::getWarehouseId, warehouseId)
.eq(ErpStockDO::getAreaId, areaId));
}
List<ErpStockDO> stockList = selectList(new LambdaQueryWrapperX<ErpStockDO>()
.eq(ErpStockDO::getProductId, productId)
.eq(ErpStockDO::getWarehouseId, warehouseId)
.eq(areaId != null, ErpStockDO::getAreaId, areaId)
.isNull(areaId == null, ErpStockDO::getAreaId));
.eq(ErpStockDO::getWarehouseId, warehouseId));
if (CollUtil.isEmpty(stockList)) {
return null;
}
ErpStockDO stock = stockList.get(0);
stock.setId(null);
stock.setAreaId(null);
stock.setAreaName(null);
stock.setCount(stockList.stream()
.map(ErpStockDO::getCount)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add));
return stock;
}
default ErpStockDO selectByProductIdAndWarehouseIdAndCategoryType(Long productId, Long warehouseId, Integer categoryType) {

@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
@ -30,4 +31,9 @@ public interface ErpStockOutItemMapper extends BaseMapperX<ErpStockOutItemDO> {
List<Long> selectOutIds(@Param("productId") Long productId, @Param("warehouseId") Long warehouseId);
BigDecimal selectLockedStockCount(@Param("productId") Long productId,
@Param("warehouseId") Long warehouseId,
@Param("areaId") Long areaId,
@Param("statuses") Collection<Integer> statuses);
}

@ -3,9 +3,15 @@ package cn.iocoder.yudao.module.erp.dal.mysql.stock;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemPalletDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Mapper
public interface ErpStockOutItemPalletMapper extends BaseMapperX<ErpStockOutItemPalletDO> {
@ -21,4 +27,42 @@ public interface ErpStockOutItemPalletMapper extends BaseMapperX<ErpStockOutItem
default int deleteByOutId(Long outId) {
return delete(ErpStockOutItemPalletDO::getOutId, outId);
}
default Map<Long, BigDecimal> selectLockedPackageCountMap(Collection<Long> palletIds,
Collection<Integer> statuses,
String outType) {
if (palletIds == null || palletIds.isEmpty()) {
return Collections.emptyMap();
}
List<Map<String, Object>> list = selectLockedPackageCountList(palletIds, statuses, outType);
if (list == null || list.isEmpty()) {
return Collections.emptyMap();
}
return list.stream().collect(Collectors.toMap(
item -> ((Number) item.get("palletId")).longValue(),
item -> item.get("lockedPackageCount") == null ? BigDecimal.ZERO
: new BigDecimal(item.get("lockedPackageCount").toString()),
(count1, count2) -> count1));
}
@Select({"<script>",
"SELECT item_pallet.pallet_id AS palletId, COALESCE(SUM(item_pallet.package_count), 0) AS lockedPackageCount",
"FROM erp_stock_out_item_pallet item_pallet",
"INNER JOIN erp_stock_out stock_out ON stock_out.id = item_pallet.out_id",
"WHERE item_pallet.pallet_id IN",
"<foreach collection='palletIds' item='palletId' open='(' separator=',' close=')'>",
"#{palletId}",
"</foreach>",
"AND stock_out.out_type = #{outType}",
"<if test='statuses != null and statuses.size() > 0'>",
"AND stock_out.status IN",
"<foreach collection='statuses' item='status' open='(' separator=',' close=')'>",
"#{status}",
"</foreach>",
"</if>",
"GROUP BY item_pallet.pallet_id",
"</script>"})
List<Map<String, Object>> selectLockedPackageCountList(@Param("palletIds") Collection<Long> palletIds,
@Param("statuses") Collection<Integer> statuses,
@Param("outType") String outType);
}

@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -34,4 +35,6 @@ public interface ErpPalletService {
void regenerateCode(Long id, String code) throws UnsupportedEncodingException;
String selectPrintTemplate();
Map<Long, BigDecimal> getLockedPackageCountMap(Collection<Long> palletIds);
}

@ -12,6 +12,8 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO;
import cn.iocoder.yudao.module.erp.dal.mysql.pallet.ErpPalletMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemPalletMapper;
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService;
import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService;
@ -21,6 +23,8 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@ -40,10 +44,15 @@ import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_LOC
public class ErpPalletServiceImpl implements ErpPalletService {
private static final int ERPPALLET_PRINT_TEMPLATE_TYPE = 8;
private static final String PRODUCT_STOCK_OUT_TYPE = "产品出库";
private static final List<Integer> LOCKED_STOCK_OUT_STATUSES = Arrays.asList(
ErpAuditStatus.PROCESS.getStatus(), ErpAuditStatus.DRAFT.getStatus(), ErpAuditStatus.UN_APPROVE.getStatus());
@Resource
private ErpPalletMapper palletMapper;
@Resource
private ErpStockOutItemPalletMapper stockOutItemPalletMapper;
@Resource
private AutoCodeUtil autoCodeUtil;
@Resource
private ErpWarehouseService warehouseService;
@ -149,6 +158,12 @@ public class ErpPalletServiceImpl implements ErpPalletService {
return palletMapper.selectPrintTemplate(ERPPALLET_PRINT_TEMPLATE_TYPE);
}
@Override
public Map<Long, BigDecimal> getLockedPackageCountMap(Collection<Long> palletIds) {
return stockOutItemPalletMapper.selectLockedPackageCountMap(
palletIds, LOCKED_STOCK_OUT_STATUSES, PRODUCT_STOCK_OUT_TYPE);
}
private ErpPalletDO validatePalletExists(Long id) {
ErpPalletDO pallet = palletMapper.selectById(id);
if (pallet == null) {

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.erp.service.product;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO;
@ -49,6 +50,10 @@ public interface ErpProductCategoryService {
*/
ErpProductCategoryDO getProductCategory(Long id);
ErpProductCategoryRespVO getProductCategoryResp(Long id);
ErpProductCategoryRespVO buildProductCategoryResp(ErpProductCategoryDO category);
/**
*
*
@ -84,4 +89,4 @@ public interface ErpProductCategoryService {
*/
ErpProductCategoryDO getProductCategoryByName(String name);
}
}

@ -2,14 +2,23 @@ package cn.iocoder.yudao.module.erp.service.product;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryProcessRouteItemRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryProcessRouteItemDO;
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductCategoryMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductCategoryProcessRouteItemMapper;
import cn.iocoder.yudao.module.mes.api.processroute.ProcessRouteApi;
import cn.iocoder.yudao.module.mes.api.processroute.dto.ProcessRouteItemSnapshotRespDTO;
import cn.iocoder.yudao.module.mes.api.processroute.dto.ProcessRouteSnapshotRespDTO;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@ -29,11 +38,18 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService
@Resource
private ErpProductCategoryMapper erpProductCategoryMapper;
@Resource
private ErpProductCategoryProcessRouteItemMapper productCategoryProcessRouteItemMapper;
@Resource
private ProcessRouteApi processRouteApi;
@Resource
@Lazy // 延迟加载,避免循环依赖
private ErpProductService productService;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createProductCategory(ErpProductCategorySaveReqVO createReqVO) {
// 校验父分类编号的有效性
validateParentProductCategory(null, createReqVO.getParentId());
@ -42,12 +58,15 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService
// 插入
ErpProductCategoryDO category = BeanUtils.toBean(createReqVO, ErpProductCategoryDO.class);
fillProcessRouteSnapshot(category);
erpProductCategoryMapper.insert(category);
saveProcessRouteItemSnapshot(category.getId(), category.getProcessRouteId());
// 返回
return category.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateProductCategory(ErpProductCategorySaveReqVO updateReqVO) {
// 校验存在
validateProductCategoryExists(updateReqVO.getId());
@ -58,7 +77,10 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService
// 更新
ErpProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductCategoryDO.class);
fillProcessRouteSnapshot(updateObj);
erpProductCategoryMapper.updateById(updateObj);
productCategoryProcessRouteItemMapper.deleteByCategoryId(updateReqVO.getId());
saveProcessRouteItemSnapshot(updateReqVO.getId(), updateObj.getProcessRouteId());
}
@Override
@ -74,9 +96,43 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService
throw exception(PRODUCT_CATEGORY_EXITS_PRODUCT);
}
// 2. 删除
productCategoryProcessRouteItemMapper.deleteByCategoryId(id);
erpProductCategoryMapper.deleteById(id);
}
private void fillProcessRouteSnapshot(ErpProductCategoryDO category) {
if (category.getProcessRouteId() == null) {
category.setProcessRouteName(null);
return;
}
ProcessRouteSnapshotRespDTO processRoute = processRouteApi.getProcessRouteSnapshot(category.getProcessRouteId());
category.setProcessRouteName(processRoute == null ? null : processRoute.getName());
}
private void saveProcessRouteItemSnapshot(Long categoryId, Long processRouteId) {
if (categoryId == null || processRouteId == null) {
return;
}
ProcessRouteSnapshotRespDTO processRoute = processRouteApi.getProcessRouteSnapshot(processRouteId);
if (processRoute == null || processRoute.getItems() == null || processRoute.getItems().isEmpty()) {
return;
}
List<ErpProductCategoryProcessRouteItemDO> saveList = new ArrayList<>();
for (ProcessRouteItemSnapshotRespDTO item : processRoute.getItems()) {
ErpProductCategoryProcessRouteItemDO snapshot = new ErpProductCategoryProcessRouteItemDO();
snapshot.setCategoryId(categoryId);
snapshot.setProcessRouteId(processRouteId);
snapshot.setProcessRouteItemId(item.getId());
snapshot.setSort(item.getSort());
snapshot.setProcessParameterId(item.getProcessParameterId());
snapshot.setProcessParameterCode(item.getProcessParameterCode());
snapshot.setProcessParameterName(item.getProcessParameterName());
snapshot.setRemark(item.getRemark());
saveList.add(snapshot);
}
productCategoryProcessRouteItemMapper.insertBatch(saveList);
}
private void validateProductCategoryExists(Long id) {
if (erpProductCategoryMapper.selectById(id) == null) {
throw exception(PRODUCT_CATEGORY_NOT_EXISTS);
@ -136,6 +192,22 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService
return erpProductCategoryMapper.selectById(id);
}
@Override
public ErpProductCategoryRespVO getProductCategoryResp(Long id) {
return buildProductCategoryResp(getProductCategory(id));
}
@Override
public ErpProductCategoryRespVO buildProductCategoryResp(ErpProductCategoryDO category) {
if (category == null) {
return null;
}
ErpProductCategoryRespVO respVO = BeanUtils.toBean(category, ErpProductCategoryRespVO.class);
List<ErpProductCategoryProcessRouteItemDO> items = productCategoryProcessRouteItemMapper.selectListByCategoryId(category.getId());
respVO.setProcessRouteItems(BeanUtils.toBean(items, ErpProductCategoryProcessRouteItemRespVO.class));
return respVO;
}
@Override
public List<ErpProductCategoryDO> getProductCategoryList(ErpProductCategoryListReqVO listReqVO) {
return erpProductCategoryMapper.selectList(listReqVO);
@ -151,4 +223,4 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService
return erpProductCategoryMapper.selectByName(name);
}
}
}

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.service.product;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductImportExcelVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductProcessRouteRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductImportRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductListReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO;
@ -67,6 +68,8 @@ public interface ErpProductService {
ErpProductRespVO getProduct(Long id, String code);
ErpProductProcessRouteRespVO getProductProcessRoute(Long productId);
/**
* VO
*

@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.*;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpPackagingSchemeDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO;
@ -417,6 +418,12 @@ public class ErpProductServiceImpl implements ErpProductService {
.ifPresent(item -> respVO.setDefaultSupplierId(item.getSupplierId()));
if (erpProductCategoryDO !=null ){
respVO.setCategoryType(erpProductCategoryDO.getType());
ErpProductCategoryRespVO categoryRespVO = productCategoryService.buildProductCategoryResp(erpProductCategoryDO);
if (categoryRespVO != null) {
respVO.setProcessRouteId(categoryRespVO.getProcessRouteId());
respVO.setProcessRouteName(categoryRespVO.getProcessRouteName());
respVO.setProcessRouteItems(categoryRespVO.getProcessRouteItems());
}
}
if (respVO.getPurchaseUnitId() != null && respVO.getPurchaseUnitName() == null) {
ErpProductUnitDO purchaseUnit = productUnitService.getProductUnit(respVO.getPurchaseUnitId());
@ -522,6 +529,27 @@ public class ErpProductServiceImpl implements ErpProductService {
throw exception(PRODUCT_NOT_EXISTS);
}
@Override
public ErpProductProcessRouteRespVO getProductProcessRoute(Long productId) {
ErpProductDO product = productMapper.selectById(productId);
if (product == null) {
return null;
}
ErpProductProcessRouteRespVO respVO = new ErpProductProcessRouteRespVO();
respVO.setProductId(productId);
Long categoryId = product.getSubCategoryId() != null ? product.getSubCategoryId() : product.getCategoryId();
if (categoryId == null) {
return respVO;
}
ErpProductCategoryRespVO categoryRespVO = productCategoryService.buildProductCategoryResp(productCategoryMapper.selectById(categoryId));
if (categoryRespVO != null) {
respVO.setProcessRouteId(categoryRespVO.getProcessRouteId());
respVO.setProcessRouteName(categoryRespVO.getProcessRouteName());
respVO.setProcessRouteItems(categoryRespVO.getProcessRouteItems());
}
return respVO;
}
private boolean isSpareProductCategory(ErpProductRespVO product) {
Long categoryId = product.getSubCategoryId() != null ? product.getSubCategoryId() : product.getCategoryId();
if (categoryId == null) {

@ -51,6 +51,7 @@ import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
@ -762,12 +763,15 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
if (approve) {
BigDecimal remainCount = defaultZero(pallet.getProductCount()).subtract(packageCount);
if (remainCount.compareTo(BigDecimal.ZERO) <= 0) {
pallet.setStatus(ErpPalletStatusEnum.IDLE.getStatus());
pallet.setProductId(null);
pallet.setProductName(null);
pallet.setProductCount(BigDecimal.ZERO);
pallet.setWarehouseId(null);
pallet.setAreaId(null);
palletMapper.update(null, new LambdaUpdateWrapper<ErpPalletDO>()
.eq(ErpPalletDO::getId, pallet.getId())
.set(ErpPalletDO::getStatus, ErpPalletStatusEnum.IDLE.getStatus())
.set(ErpPalletDO::getProductId, null)
.set(ErpPalletDO::getProductName, null)
.set(ErpPalletDO::getProductCount, BigDecimal.ZERO)
.set(ErpPalletDO::getWarehouseId, null)
.set(ErpPalletDO::getAreaId, null));
return;
} else {
pallet.setProductCount(remainCount);
}

@ -15,4 +15,27 @@
</where>
</select>
<select id="selectLockedStockCount" resultType="java.math.BigDecimal">
SELECT COALESCE(SUM(item.count), 0)
FROM erp_stock_out_item item
INNER JOIN erp_stock_out stock_out ON stock_out.id = item.out_id
<where>
<if test="productId != null">
AND item.product_id = #{productId}
</if>
<if test="warehouseId != null">
AND item.warehouse_id = #{warehouseId}
</if>
<if test="areaId != null">
AND item.area_id = #{areaId}
</if>
<if test="statuses != null and statuses.size() > 0">
AND stock_out.status IN
<foreach collection="statuses" item="status" open="(" separator="," close=")">
#{status}
</foreach>
</if>
</where>
</select>
</mapper>

@ -0,0 +1,12 @@
package cn.iocoder.yudao.module.mes.api.processroute;
import cn.iocoder.yudao.module.mes.api.processroute.dto.ProcessRouteSnapshotRespDTO;
/**
* 线 API
*/
public interface ProcessRouteApi {
ProcessRouteSnapshotRespDTO getProcessRouteSnapshot(Long id);
}

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.mes.api.processroute.dto;
import lombok.Data;
/**
* 线 DTO
*/
@Data
public class ProcessRouteItemSnapshotRespDTO {
private Long id;
private Long routeId;
private Integer sort;
private Long processParameterId;
private String processParameterCode;
private String processParameterName;
private String remark;
}

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.mes.api.processroute.dto;
import lombok.Data;
import java.util.List;
/**
* 线 DTO
*/
@Data
public class ProcessRouteSnapshotRespDTO {
private Long id;
private String code;
private String name;
private List<ProcessRouteItemSnapshotRespDTO> items;
}

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.mes.api.processroute;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.mes.api.processroute.dto.ProcessRouteItemSnapshotRespDTO;
import cn.iocoder.yudao.module.mes.api.processroute.dto.ProcessRouteSnapshotRespDTO;
import cn.iocoder.yudao.module.mes.dal.dataobject.processroute.ProcessRouteDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.processroute.ProcessRouteItemDO;
import cn.iocoder.yudao.module.mes.dal.mysql.processroute.ProcessRouteItemMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.processroute.ProcessRouteMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* 线 API
*/
@Service
public class ProcessRouteApiImpl implements ProcessRouteApi {
@Resource
private ProcessRouteMapper processRouteMapper;
@Resource
private ProcessRouteItemMapper processRouteItemMapper;
@Override
public ProcessRouteSnapshotRespDTO getProcessRouteSnapshot(Long id) {
if (id == null) {
return null;
}
ProcessRouteDO processRoute = processRouteMapper.selectById(id);
if (processRoute == null) {
return null;
}
ProcessRouteSnapshotRespDTO respDTO = BeanUtils.toBean(processRoute, ProcessRouteSnapshotRespDTO.class);
List<ProcessRouteItemDO> items = processRouteItemMapper.selectListByRouteId(id);
respDTO.setItems(BeanUtils.toBean(items, ProcessRouteItemSnapshotRespDTO.class));
return respDTO;
}
}

@ -705,12 +705,19 @@ public class PlanController {
return success(true);
}
@GetMapping("/line-change-record/list")
@Operation(summary = "获得生产计划换线记录列表")
@Parameter(name = "planId", description = "生产计划 ID", required = true, example = "1024")
@PutMapping("/change-line-batch")
@Operation(summary = "生产计划批量换线")
@PreAuthorize("@ss.hasPermission('mes:plan:update')")
public CommonResult<Boolean> changeLineBatch(@Valid @RequestBody PlanLineChangeBatchReqVO reqVO) {
planService.changeLineBatch(reqVO);
return success(true);
}
@GetMapping("/line-change-record/page")
@Operation(summary = "获得生产计划换线记录分页")
@PreAuthorize("@ss.hasPermission('mes:plan:query')")
public CommonResult<List<PlanLineChangeRecordRespVO>> getLineChangeRecordList(@RequestParam("planId") Long planId) {
return success(planService.getLineChangeRecordList(planId));
public CommonResult<PageResult<PlanLineChangeRecordBatchRespVO>> getLineChangeRecordPage(@Valid PlanLineChangeRecordPageReqVO pageReqVO) {
return success(planService.getLineChangeRecordPage(pageReqVO));
}

@ -0,0 +1,44 @@
package cn.iocoder.yudao.module.mes.controller.admin.plan.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Schema(description = "管理后台 - 生产计划批量换线 Request VO")
@Data
public class PlanLineChangeBatchReqVO {
@Schema(description = "生产计划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "生产计划 ID 不能为空")
private Long planId;
@Valid
@NotEmpty(message = "换线明细列表不能为空")
@Schema(description = "换线明细列表", implementation = LineChangeItem.class)
private List<LineChangeItem> items;
@Schema(description = "备注")
private String remark;
@Data
@Schema(description = "生产计划批量换线明细")
public static class LineChangeItem {
@Schema(description = "计划工艺流程明细 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "计划工艺流程明细 ID 不能为空")
private Long planProcessRouteItemId;
@Schema(description = "换线后的设备 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "换线后的设备 ID 不能为空")
private Long deviceId;
@Schema(description = "备注")
private String remark;
}
}

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.mes.controller.admin.plan.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 生产计划换线记录批次 Response VO")
@Data
public class PlanLineChangeRecordBatchRespVO {
@Schema(description = "换线批次号", example = "B20260706000001")
private String changeBatchNo;
@Schema(description = "生产计划编号", example = "1")
private Long planId;
@Schema(description = "换线时间")
private LocalDateTime changeTime;
@Schema(description = "操作人 ID", example = "1")
private Long operatorUserId;
@Schema(description = "操作人名字", example = "张三")
private String operatorUserName;
@Schema(description = "当前计划合格数量", example = "100")
private Long passNumber;
@Schema(description = "备注")
private String remark;
@Schema(description = "变更工序数量", example = "2")
private Integer changeCount;
@Schema(description = "换线明细列表")
private List<PlanLineChangeRecordRespVO> items;
}

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.mes.controller.admin.plan.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 生产计划换线记录分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PlanLineChangeRecordPageReqVO extends PageParam {
@Schema(description = "生产计划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "生产计划 ID 不能为空")
private Long planId;
}

@ -15,6 +15,9 @@ public class PlanLineChangeRecordRespVO {
@Schema(description = "生产计划编号", example = "1")
private Long planId;
@Schema(description = "换线批次号", example = "B202607060001")
private String changeBatchNo;
@Schema(description = "计划工艺流程明细编号", example = "1")
private Long planProcessRouteItemId;

@ -11,11 +11,14 @@ public enum PlanStatusEnum {
(1),
(2),
(3),
(4),
//旧完工-启用
// 完工(4),
(5),
(6),
(7),
(8);
(8),
(9);
private final int value;

@ -30,6 +30,10 @@ public class PlanLineChangeRecordDO extends BaseDO {
*
*/
private Long planId;
/**
* 线
*/
private String changeBatchNo;
/**
*
*/

@ -1,7 +1,9 @@
package cn.iocoder.yudao.module.mes.dal.mysql.planlinechange;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanLineChangeRecordPageReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.planlinechange.PlanLineChangeRecordDO;
import org.apache.ibatis.annotations.Mapper;
@ -17,4 +19,11 @@ public interface PlanLineChangeRecordMapper extends BaseMapperX<PlanLineChangeRe
.orderByDesc(PlanLineChangeRecordDO::getId));
}
default PageResult<PlanLineChangeRecordDO> selectPage(PlanLineChangeRecordPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<PlanLineChangeRecordDO>()
.eq(PlanLineChangeRecordDO::getPlanId, reqVO.getPlanId())
.orderByDesc(PlanLineChangeRecordDO::getChangeTime)
.orderByDesc(PlanLineChangeRecordDO::getId));
}
}

@ -64,6 +64,10 @@ public class MesNoRedisDAO {
*
*/
public static final String REPORT_NO_PREFIX = "WR-";
/**
* 线
*/
public static final String PLAN_LINE_CHANGE_BATCH_NO_PREFIX = "B";
/**
*
*/

@ -115,9 +115,11 @@ public interface PlanService {
PageResult<PlanProductCapacityRespVO> getPlanProductCapacityPage(PlanProductCapacityPageReqVO reqVO);
void changeLine(@Valid PlanLineChangeReqVO reqVO);
void changeLine(@Valid PlanLineChangeReqVO reqVO);
List<PlanLineChangeRecordRespVO> getLineChangeRecordList(Long planId);
void changeLineBatch(@Valid PlanLineChangeBatchReqVO reqVO);
PageResult<PlanLineChangeRecordBatchRespVO> getLineChangeRecordPage(PlanLineChangeRecordPageReqVO pageReqVO);
}

@ -989,35 +989,110 @@ public class PlanServiceImpl implements PlanService {
if (plan == null) {
throw exception(PLAN_NOT_EXISTS);
}
PlanProcessRouteItemDO planRouteItem = planProcessRouteItemMapper.selectById(reqVO.getPlanProcessRouteItemId());
if (planRouteItem == null || !Objects.equals(planRouteItem.getPlanId(), reqVO.getPlanId())) {
String changeBatchNo = noRedisDAO.generate6(MesNoRedisDAO.PLAN_LINE_CHANGE_BATCH_NO_PREFIX);
changeLineItem(plan, reqVO.getPlanProcessRouteItemId(), reqVO.getDeviceId(), reqVO.getRemark(), changeBatchNo,
LocalDateTime.now(), getLoginUserId());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void changeLineBatch(PlanLineChangeBatchReqVO reqVO) {
PlanDO plan = planMapper.selectById(reqVO.getPlanId());
if (plan == null) {
throw exception(PLAN_NOT_EXISTS);
}
DeviceLedgerDO afterDevice = deviceLedgerMapper.selectById(reqVO.getDeviceId());
String changeBatchNo = null;
LocalDateTime changeTime = LocalDateTime.now();
Long operatorUserId = getLoginUserId();
for (PlanLineChangeBatchReqVO.LineChangeItem item : reqVO.getItems()) {
PlanProcessRouteItemDO planRouteItem = planProcessRouteItemMapper.selectById(item.getPlanProcessRouteItemId());
if (planRouteItem == null || !Objects.equals(planRouteItem.getPlanId(), plan.getId())) {
throw exception(PLAN_NOT_EXISTS);
}
if (Objects.equals(planRouteItem.getDeviceId(), item.getDeviceId())) {
continue;
}
if (changeBatchNo == null) {
changeBatchNo = noRedisDAO.generate6(MesNoRedisDAO.PLAN_LINE_CHANGE_BATCH_NO_PREFIX);
}
String remark = item.getRemark() != null ? item.getRemark() : reqVO.getRemark();
changeLineItem(plan, planRouteItem, item.getDeviceId(), remark, changeBatchNo,
changeTime, operatorUserId);
}
}
private void changeLineItem(PlanDO plan, Long planProcessRouteItemId, Long deviceId, String remark,
String changeBatchNo, LocalDateTime changeTime, Long operatorUserId) {
PlanProcessRouteItemDO planRouteItem = planProcessRouteItemMapper.selectById(planProcessRouteItemId);
if (planRouteItem == null || !Objects.equals(planRouteItem.getPlanId(), plan.getId())) {
throw exception(PLAN_NOT_EXISTS);
}
changeLineItem(plan, planRouteItem, deviceId, remark, changeBatchNo, changeTime, operatorUserId);
}
private void changeLineItem(PlanDO plan, PlanProcessRouteItemDO planRouteItem, Long deviceId, String remark,
String changeBatchNo, LocalDateTime changeTime, Long operatorUserId) {
DeviceLedgerDO afterDevice = deviceLedgerMapper.selectById(deviceId);
PlanLineChangeRecordDO record = new PlanLineChangeRecordDO();
record.setPlanId(plan.getId());
record.setChangeBatchNo(changeBatchNo);
record.setPlanProcessRouteItemId(planRouteItem.getId());
record.setProcessParameterId(planRouteItem.getProcessParameterId());
record.setProcessParameterName(planRouteItem.getProcessParameterName());
record.setBeforeDeviceId(planRouteItem.getDeviceId());
record.setBeforeDeviceName(planRouteItem.getDeviceName());
record.setAfterDeviceId(reqVO.getDeviceId());
record.setAfterDeviceId(deviceId);
record.setAfterDeviceName(afterDevice == null ? null : afterDevice.getDeviceName());
record.setChangeTime(LocalDateTime.now());
record.setOperatorUserId(getLoginUserId());
record.setChangeTime(changeTime);
record.setOperatorUserId(operatorUserId);
record.setPassNumber(plan.getPassNumber());
record.setRemark(reqVO.getRemark());
record.setRemark(remark);
planLineChangeRecordMapper.insert(record);
planRouteItem.setDeviceId(reqVO.getDeviceId());
planRouteItem.setDeviceId(deviceId);
planRouteItem.setDeviceName(afterDevice == null ? null : afterDevice.getDeviceName());
planProcessRouteItemMapper.updateById(planRouteItem);
}
@Override
public List<PlanLineChangeRecordRespVO> getLineChangeRecordList(Long planId) {
return BeanUtils.toBean(planLineChangeRecordMapper.selectListByPlanId(planId), PlanLineChangeRecordRespVO.class);
public PageResult<PlanLineChangeRecordBatchRespVO> getLineChangeRecordPage(PlanLineChangeRecordPageReqVO pageReqVO) {
List<PlanLineChangeRecordDO> records = planLineChangeRecordMapper.selectListByPlanId(pageReqVO.getPlanId());
if (CollUtil.isEmpty(records)) {
return new PageResult<>(Collections.emptyList(), 0L);
}
Map<String, List<PlanLineChangeRecordDO>> batchMap = records.stream()
.collect(Collectors.groupingBy(this::getLineChangeBatchKey, LinkedHashMap::new, Collectors.toList()));
List<PlanLineChangeRecordBatchRespVO> batchList = batchMap.entrySet().stream()
.map(entry -> buildLineChangeBatchRespVO(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
Map<Long, AdminUserDO> operatorUserMap = userService.getUserMap(
batchList.stream().map(PlanLineChangeRecordBatchRespVO::getOperatorUserId)
.filter(Objects::nonNull).collect(Collectors.toSet()));
batchList.forEach(batch -> MapUtils.findAndThen(operatorUserMap, batch.getOperatorUserId(),
user -> batch.setOperatorUserName(user.getNickname())));
int fromIndex = Math.min((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize(), batchList.size());
int toIndex = Math.min(fromIndex + pageReqVO.getPageSize(), batchList.size());
return new PageResult<>(batchList.subList(fromIndex, toIndex), (long) batchList.size());
}
private String getLineChangeBatchKey(PlanLineChangeRecordDO record) {
return StringUtils.isNotBlank(record.getChangeBatchNo()) ? record.getChangeBatchNo() : String.valueOf(record.getId());
}
private PlanLineChangeRecordBatchRespVO buildLineChangeBatchRespVO(String changeBatchNo,
List<PlanLineChangeRecordDO> records) {
PlanLineChangeRecordDO firstRecord = records.get(0);
PlanLineChangeRecordBatchRespVO respVO = new PlanLineChangeRecordBatchRespVO();
respVO.setChangeBatchNo(changeBatchNo);
respVO.setPlanId(firstRecord.getPlanId());
respVO.setChangeTime(firstRecord.getChangeTime());
respVO.setOperatorUserId(firstRecord.getOperatorUserId());
respVO.setPassNumber(firstRecord.getPassNumber());
respVO.setRemark(firstRecord.getRemark());
respVO.setChangeCount(records.size());
respVO.setItems(BeanUtils.toBean(records, PlanLineChangeRecordRespVO.class));
return respVO;
}

Loading…
Cancel
Save