新增订单贴皮关联和代码修改

This commit is contained in:
gaoqr
2026-08-05 14:12:20 +08:00
parent addd8342b2
commit cb69c5ab7b
30 changed files with 721 additions and 501 deletions
@@ -215,6 +215,8 @@ public class ErrorCodeConstants {
public static final ErrorCode VENEER_DECOMPOSE_PLATE_SIZE_INVALID = new ErrorCode(1_003_009_052, "veneer.decompose.plate.size.invalid");
public static final ErrorCode VENEER_DECOMPOSE_ORDER_IDS_REQUIRED = new ErrorCode(1_003_009_053, "veneer.decompose.order.ids.required");
public static final ErrorCode VENEER_DECOMPOSE_GOODS_IDS_REQUIRED = new ErrorCode(1_003_009_054, "veneer.decompose.goods.ids.required");
public static final ErrorCode ORDER_VENEER_GOODS_CREATE_FAILED = new ErrorCode(1_003_009_055, "order.veneer.goods.create.failed");
public static final ErrorCode ORDER_VENEER_GOODS_STATUS_CHANGED = new ErrorCode(1_003_009_056, "order.veneer.goods.status.changed");
//=========== 部件管理 1-003-010-000 ============
public static final ErrorCode ORDER_COMPONENT_NOT_EXIST = new ErrorCode(1_003_010_000, "order.component.not.exist");
@@ -49,13 +49,13 @@ public class UnplannedVeneerController {
}
/**
* 分页查询存在未排贴皮的板材
* 分页查询存在未排贴皮的贴皮商品
*
* @param req 分页及筛选条件
* @return 板材分页列表
* @return 贴皮商品分页列表
*/
@PostMapping("/goods/page")
@Operation(summary = "获取未排贴皮板材分页列表")
@Operation(summary = "获取未排贴皮商品分页列表")
@PreAuthorize("@ss.hasPermission('unplannedOrders:query')")
public CommonResult<PageResult<VeneerManageGoodsRespVO>> getUnplannedVeneerGoodsPage(
@Valid @RequestBody VeneerManageGoodsPageReqVO req) {
@@ -63,9 +63,9 @@ public class UnplannedVeneerController {
}
/**
* 按订单或板材查询未排贴皮、原板件及板件造型数据。
* 按订单或贴皮商品查询未排贴皮、原板件及板件造型数据。
*
* @param req 订单和/或板材查询范围及可选房间、柜体条件
* @param req 订单和/或贴皮商品查询范围及可选房间、柜体条件
* @return 未排贴皮排单基础数据
*/
@PostMapping("/plate/data")
@@ -53,13 +53,13 @@ public class VeneerManageController {
}
/**
* 分页查询存在可维护未排单贴皮的板材
* 分页查询存在可维护未排单贴皮的贴皮商品
*
* @param req 分页及筛选条件
* @return 板材分页列表
* @return 贴皮商品分页列表
*/
@PostMapping("/goods/page")
@Operation(summary = "获取贴皮管理板材分页列表")
@Operation(summary = "获取贴皮管理商品分页列表")
@PreAuthorize("@ss.hasPermission('unplannedOrders:query')")
public CommonResult<PageResult<VeneerManageGoodsRespVO>> getVeneerManageGoodsPage(
@Valid @RequestBody VeneerManageGoodsPageReqVO req) {
@@ -81,13 +81,13 @@ public class VeneerManageController {
}
/**
* 按板材查询可维护的未排单板件贴皮列表。
* 按贴皮商品查询可维护的未排单板件贴皮列表。
*
* @param req 查询条件,必须包含板材商品编码列表
* @param req 查询条件,必须包含贴皮商品编码列表
* @return 未排单板件贴皮列表
*/
@PostMapping("/goods/plate/list")
@Operation(summary = "板材获取可维护的未排单板件贴皮列表")
@Operation(summary = "贴皮商品获取可维护的未排单板件贴皮列表")
@PreAuthorize("@ss.hasPermission('unplannedOrders:query')")
public CommonResult<List<VeneerManagePlateRespVO>> getVeneerManageGoodsPlateList(
@Valid @RequestBody VeneerManagePlateListReqVO req) {
@@ -14,10 +14,10 @@ import java.util.List;
@Data
public class UnplannedVeneerPlateDataReqVO {
@Schema(description = "订单ID列表,与板材商品编码列表至少传入一项")
@Schema(description = "订单ID列表,与贴皮商品编码列表至少传入一项")
private List<Long> orderIds;
@Schema(description = "板材商品编码列表,与订单ID列表至少传入一项")
@Schema(description = "贴皮商品编码列表,与订单ID列表至少传入一项")
private List<String> goodsIds;
@Schema(description = "房间ID列表")
@@ -22,6 +22,9 @@ public class UnplannedVeneerPlateRespVO extends VeneerDecomposePlateRespVO {
@Schema(description = "订单板材ID")
private Long orderGoodsId;
@Schema(description = "订单贴皮商品ID")
private Long orderVeneerGoodsId;
@Schema(description = "贴皮逻辑面:A-A面,B-B面")
private String veneerSide;
@@ -4,12 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 贴皮板材分组关联订单响应参数。
* 贴皮商品分组关联订单响应参数。
*/
@Data
public class VeneerGoodsOrderRelationRespVO {
@Schema(description = "板材商品编码")
@Schema(description = "商品编码")
private String goodsId;
@Schema(description = "订单ID")
@@ -17,4 +17,7 @@ public class VeneerGoodsOrderRelationRespVO {
@Schema(description = "订单板材ID,对应 order_goods.id")
private Long orderGoodsId;
@Schema(description = "订单贴皮商品ID,对应 order_veneer_goods.id")
private Long orderVeneerGoodsId;
}
@@ -8,7 +8,7 @@ import java.math.BigDecimal;
import java.util.List;
/**
* 贴皮管理板材分页查询请求参数。
* 贴皮管理商品分页查询请求参数。
*/
@Data
public class VeneerManageGoodsPageReqVO extends PageParam {
@@ -22,7 +22,7 @@ public class VeneerManageGoodsPageReqVO extends PageParam {
@Schema(description = "柜体ID列表")
private List<Long> bodyIds;
@Schema(description = "板材名称")
@Schema(description = "贴皮商品名称")
private String goodsName;
@Schema(description = "商品编码")
@@ -7,15 +7,15 @@ import java.math.BigDecimal;
import java.util.List;
/**
* 贴皮管理板材分页响应参数。
* 贴皮管理商品分页响应参数。
*/
@Data
public class VeneerManageGoodsRespVO {
@Schema(description = "当前板材分组关联的订单")
@Schema(description = "当前贴皮商品分组关联的订单")
private List<VeneerGoodsOrderRelationRespVO> orderIds;
@Schema(description = "板材名称")
@Schema(description = "贴皮商品名称")
private String goodsName;
@Schema(description = "商品编码")
@@ -19,7 +19,7 @@ public class VeneerManageOrderPageReqVO extends PageParam {
@Schema(description = "精确限定的订单ID列表")
private List<Long> orderIds;
@Schema(description = "板材商品编码列表")
@Schema(description = "贴皮商品编码列表")
private List<String> goodsIds;
@Schema(description = "订单号")
@@ -20,6 +20,6 @@ public class VeneerManagePlateListReqVO {
@Schema(description = "柜体ID列表,仅按订单查询时生效")
private List<Long> bodyIds;
@Schema(description = "板材商品编码列表")
@Schema(description = "贴皮商品编码列表")
private List<String> goodsIds;
}
@@ -113,11 +113,6 @@ public class GoodsDO extends BaseDO {
*/
private Integer decomposedVeneerPlateNum;
/**
* 已排贴皮板件数量,所有有效贴皮面均已排单时计数
*/
private Integer plannedVeneerPlateNum;
/**
* 板件总面积
*/
@@ -43,6 +43,11 @@ public class OrderPlateVeneerDO extends BaseDO {
*/
private Long orderGoodsId;
/**
* 订单贴皮商品主键,对应 {@code order_veneer_goods.id}。
*/
private Long orderVeneerGoodsId;
/**
* 原板件主键,对应 {@code order_plate.id}。
*/
@@ -108,33 +113,4 @@ public class OrderPlateVeneerDO extends BaseDO {
*/
private Long planId;
/**
* 来源贴皮库记录主键,对应 {@code veneers.id}。
*/
private Long sourceVeneerId;
/**
* 贴皮商品编号快照。
*/
private String sourceVeneerNo;
/**
* 贴皮名称快照。
*/
private String veneerName;
/**
* 产品等级快照。
*/
private Integer productLevel;
/**
* 颜色快照。
*/
private String color;
/**
* 材质快照。
*/
private String material;
}
@@ -0,0 +1,74 @@
package com.cf.imes.module.executor.dal.dataobject.veneer;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* 订单贴皮商品 DO。
*
* <p>按订单和贴皮库商品归集板件贴皮,统一保存商品快照及数量统计。</p>
*/
@TableName("order_veneer_goods")
@KeySequence("order_veneer_goods_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OrderVeneerGoodsDO extends BaseDO {
/** 主键。 */
@TableId
private Long id;
/** 组织ID,也是 MyCat 分片键。 */
private Long organId;
/** 订单主键,对应 {@code orders.id}。 */
private Long orderId;
/** 来源贴皮库主键,对应 {@code veneers.id}。 */
private Long sourceVeneerId;
/** 贴皮商品编号快照。 */
private String goodsId;
/** 贴皮商品名称快照。 */
private String goodsName;
/** 产品等级快照。 */
private Integer productLevel;
/** 材质快照。 */
private String material;
/** 颜色快照。 */
private String color;
/** 厚度快照,单位:mm。 */
private BigDecimal thickness;
/** 有效贴皮总数量,A/B 面分别计数。 */
private Integer veneerNum;
/** 已排单贴皮数量。 */
private Integer plannedVeneerNum;
/** 有效贴皮总面积,单位:平方米。 */
private BigDecimal veneerArea;
/** 已排单贴皮面积,单位:平方米。 */
private BigDecimal plannedVeneerArea;
/** 乐观锁版本号。 */
private Integer version;
}
@@ -0,0 +1,10 @@
package com.cf.imes.module.executor.dal.dataobject.veneer;
/**
* 订单贴皮商品业务唯一键。
*
* @param orderId 订单主键
* @param sourceVeneerId 来源贴皮库主键
*/
public record OrderVeneerGoodsKey(Long orderId, Long sourceVeneerId) {
}
@@ -0,0 +1,27 @@
package com.cf.imes.module.executor.dal.dataobject.veneer;
import lombok.Data;
import java.math.BigDecimal;
/**
* 订单贴皮商品数量及面积统计结果。
*/
@Data
public class OrderVeneerGoodsStatisticsDO {
/** 订单贴皮商品主键。 */
private Long orderVeneerGoodsId;
/** 有效贴皮总数量。 */
private Integer veneerNum;
/** 已排单贴皮数量。 */
private Integer plannedVeneerNum;
/** 有效贴皮总面积。 */
private BigDecimal veneerArea;
/** 已排单贴皮面积。 */
private BigDecimal plannedVeneerArea;
}
@@ -0,0 +1,14 @@
package com.cf.imes.module.executor.dal.mysql.veneer;
import com.cf.imes.framework.mybatis.core.injector.BaseBatchMapper;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 订单贴皮商品批量 Mapper。
*
* <p>使用单条 {@code INSERT ... VALUES (...), (...)} SQL 批量写入。</p>
*/
@Mapper
public interface OrderVeneerGoodsBatchMapper extends BaseBatchMapper<OrderVeneerGoodsDO> {
}
@@ -0,0 +1,24 @@
package com.cf.imes.module.executor.dal.mysql.veneer;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsStatisticsDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 订单贴皮商品 Mapper。
*/
@Mapper
public interface OrderVeneerGoodsMapper extends BaseMapperX<OrderVeneerGoodsDO> {
/**
* 根据板件贴皮明细重新统计订单贴皮商品数量及面积。
*
* @param ids 订单贴皮商品主键列表
* @return 有明细的商品统计结果
*/
List<OrderVeneerGoodsStatisticsDO> selectStatistics(@Param("ids") List<Long> ids);
}
@@ -59,21 +59,21 @@ public interface VeneerManageMapper {
@Param("orderDateTime") LocalDateTime[] orderDateTime);
/**
* 分页查询存在可维护未排单贴皮的板材
* 分页查询存在可维护未排单贴皮的贴皮商品
*
* @param page 分页参数
* @param req 板材查询条件
* @return 板材分页结果
* @param req 贴皮商品查询条件
* @return 贴皮商品分页结果
*/
IPage<VeneerManageGoodsRespVO> selectGoodsPage(@Param("page") IPage<VeneerManageGoodsRespVO> page,
@Param("req") VeneerManageGoodsPageReqVO req);
/**
* 查询当前页贴皮管理板材分组关联的订单。
* 查询当前页贴皮商品分组关联的订单。
*
* @param goodsIds 当前页板材商品编码
* @param goodsIds 当前页贴皮商品编码
* @param req 订单、房间及柜体筛选条件
* @return 板材与订单关系
* @return 贴皮商品与订单关系
*/
List<VeneerGoodsOrderRelationRespVO> selectGoodsOrderRelationList(
@Param("goodsIds") List<String> goodsIds,
@@ -105,28 +105,6 @@ public interface VeneerManageMapper {
@Param("req") VeneerManageOrderPageReqVO req,
@Param("orderDateTime") LocalDateTime[] orderDateTime);
/**
* 分页查询存在待排单贴皮的板材。
*
* @param page 分页参数
* @param req 板材查询条件
* @return 板材分页结果
*/
IPage<VeneerManageGoodsRespVO> selectUnplannedGoodsPage(
@Param("page") IPage<VeneerManageGoodsRespVO> page,
@Param("req") VeneerManageGoodsPageReqVO req);
/**
* 查询当前页未排贴皮板材分组关联的订单。
*
* @param goodsIds 当前页板材商品编码
* @param req 订单、房间及柜体筛选条件
* @return 板材与订单关系
*/
List<VeneerGoodsOrderRelationRespVO> selectUnplannedGoodsOrderRelationList(
@Param("goodsIds") List<String> goodsIds,
@Param("req") VeneerManageGoodsPageReqVO req);
/**
* 按订单查询可维护的未排单板件贴皮列表。
*
@@ -136,19 +114,19 @@ public interface VeneerManageMapper {
List<VeneerManagePlateRespVO> selectOrderPlateList(@Param("req") VeneerManagePlateListReqVO req);
/**
* 按板材商品编码查询可维护的未排单板件贴皮列表。
* 按贴皮商品编码查询可维护的未排单板件贴皮列表。
*
* @param req 订单、板材、房间及柜体查询条件
* @param req 订单、贴皮商品、房间及柜体查询条件
* @return 未排单板件贴皮列表
*/
List<VeneerManagePlateRespVO> selectGoodsPlateList(
@Param("req") VeneerManagePlateListReqVO req);
/**
* 按订单和/或板材范围查询待排单贴皮及其原板件信息。
* 按订单和/或贴皮商品范围查询待排单贴皮及其原板件信息。
* 同一贴皮可能因多个加工组返回多条,由 Service 层合并。
*
* @param req 订单或板材范围及房间、柜体筛选条件
* @param req 订单或贴皮商品范围及房间、柜体筛选条件
* @return 待排单贴皮及原板件原始列表
*/
List<UnplannedVeneerPlateRespVO> selectUnplannedPlateList(
@@ -139,19 +139,10 @@ public interface VeneerPlanMapper extends BaseMapperX<OrderVeneerPlanDO> {
@Param("orderIds") List<Long> orderIds);
/**
* 按订单材质重新统计所有有效贴皮面均已排单的原始板件数量
*
* @param orderGoodsIds {@code order_goods} 主键列表
* @return 订单材质及其所有贴皮面均已排单的板件数量
*/
List<VeneerPlannedPlateCountDO> selectGoodsPlannedVeneerPlateCount(
@Param("orderGoodsIds") List<Long> orderGoodsIds);
/**
* 查询待删除排单影响的订单和订单材质范围。
* 查询待删除排单影响的订单和订单贴皮商品范围
*
* @param planIds 贴皮排单ID列表
* @return 受影响的订单及订单材质
* @return 受影响的订单及订单贴皮商品
*/
List<OrderPlateVeneerDO> selectPlanAffectedScope(@Param("planIds") List<Long> planIds);
@@ -0,0 +1,32 @@
package com.cf.imes.module.executor.service.veneer;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsKey;
import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDO;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 订单贴皮商品 Service。
*/
public interface OrderVeneerGoodsService {
/**
* 查询或创建订单与贴皮库商品的归集关系。
*
* @param orderIds 订单主键列表
* @param sourceVeneers 来源贴皮库商品
* @return 订单和来源贴皮库主键对应的订单贴皮商品
*/
Map<OrderVeneerGoodsKey, OrderVeneerGoodsDO> getOrCreate(
List<Long> orderIds, Collection<VeneerDO> sourceVeneers);
/**
* 根据有效板件贴皮明细重新统计数量及面积。
*
* @param orderVeneerGoodsIds 订单贴皮商品主键集合
*/
void refreshStatistics(Collection<Long> orderVeneerGoodsIds);
}
@@ -0,0 +1,171 @@
package com.cf.imes.module.executor.service.veneer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.security.core.LoginUser;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsKey;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsStatisticsDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDO;
import com.cf.imes.module.executor.dal.mysql.veneer.OrderVeneerGoodsBatchMapper;
import com.cf.imes.module.executor.dal.mysql.veneer.OrderVeneerGoodsMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_VENEER_GOODS_CREATE_FAILED;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_VENEER_GOODS_STATUS_CHANGED;
/**
* 订单贴皮商品 Service 实现。
*/
@Service
public class OrderVeneerGoodsServiceImpl implements OrderVeneerGoodsService {
/** 查询、插入及统计的单批处理数量。 */
private static final int BATCH_SIZE = 100;
@Resource
private OrderVeneerGoodsMapper orderVeneerGoodsMapper;
@Resource
private OrderVeneerGoodsBatchMapper orderVeneerGoodsBatchMapper;
@Resource
private IdentifierGenerator identifierGenerator;
@Override
public Map<OrderVeneerGoodsKey, OrderVeneerGoodsDO> getOrCreate(
List<Long> orderIds, Collection<VeneerDO> sourceVeneers) {
List<Long> normalizedOrderIds = orderIds.stream().filter(Objects::nonNull)
.distinct().sorted().toList();
Map<Long, VeneerDO> sourceVeneerMap = new HashMap<>();
for (VeneerDO sourceVeneer : sourceVeneers) {
sourceVeneerMap.put(sourceVeneer.getId(), sourceVeneer);
}
if (CollUtil.isEmpty(normalizedOrderIds) || sourceVeneerMap.isEmpty()) {
return Map.of();
}
// 分批加载已存在的订单贴皮商品,避免订单数量较大时形成超长 IN 条件。
Map<OrderVeneerGoodsKey, OrderVeneerGoodsDO> result = new HashMap<>();
List<Long> sourceVeneerIds = new ArrayList<>(sourceVeneerMap.keySet());
for (List<Long> orderIdBatch : CollUtil.split(normalizedOrderIds, BATCH_SIZE)) {
List<OrderVeneerGoodsDO> existingList = orderVeneerGoodsMapper.selectList(
new LambdaQueryWrapper<OrderVeneerGoodsDO>()
.in(OrderVeneerGoodsDO::getOrderId, orderIdBatch)
.in(OrderVeneerGoodsDO::getSourceVeneerId, sourceVeneerIds));
for (OrderVeneerGoodsDO existing : existingList) {
result.put(new OrderVeneerGoodsKey(
existing.getOrderId(), existing.getSourceVeneerId()), existing);
}
}
LoginUser loginUser = Objects.requireNonNull(SecurityFrameworkUtils.getLoginUser());
LocalDateTime now = LocalDateTime.now();
List<OrderVeneerGoodsDO> createdList = new ArrayList<>();
for (Long orderId : normalizedOrderIds) {
for (VeneerDO sourceVeneer : sourceVeneerMap.values()) {
OrderVeneerGoodsKey key = new OrderVeneerGoodsKey(orderId, sourceVeneer.getId());
if (result.containsKey(key)) {
continue;
}
OrderVeneerGoodsDO created = buildOrderVeneerGoods(
orderId, sourceVeneer, loginUser, now);
result.put(key, created);
createdList.add(created);
}
}
// 使用 BaseBatchMapper 分批执行多值 INSERT,控制单条 SQL 的参数量。
for (List<OrderVeneerGoodsDO> batch : CollUtil.split(createdList, BATCH_SIZE)) {
int inserted = orderVeneerGoodsBatchMapper.insertBatchSomeColumn(batch);
if (inserted != batch.size()) {
throw new ServiceException(ORDER_VENEER_GOODS_CREATE_FAILED);
}
}
return result;
}
@Override
public void refreshStatistics(Collection<Long> orderVeneerGoodsIds) {
List<Long> ids = orderVeneerGoodsIds.stream().filter(Objects::nonNull)
.distinct().sorted().toList();
for (List<Long> idBatch : CollUtil.split(ids, BATCH_SIZE)) {
Map<Long, OrderVeneerGoodsStatisticsDO> statisticsMap = new HashMap<>();
for (OrderVeneerGoodsStatisticsDO statistics
: orderVeneerGoodsMapper.selectStatistics(idBatch)) {
statisticsMap.put(statistics.getOrderVeneerGoodsId(), statistics);
}
List<OrderVeneerGoodsDO> goodsList = orderVeneerGoodsMapper.selectList(
new LambdaQueryWrapper<OrderVeneerGoodsDO>()
.select(OrderVeneerGoodsDO::getId, OrderVeneerGoodsDO::getVersion)
.in(OrderVeneerGoodsDO::getId, idBatch));
if (goodsList.size() != idBatch.size()) {
throw new ServiceException(ORDER_VENEER_GOODS_STATUS_CHANGED);
}
// 每行携带 version 条件更新,避免并发操作覆盖统计结果。
for (OrderVeneerGoodsDO goods : goodsList) {
OrderVeneerGoodsStatisticsDO statistics = statisticsMap.get(goods.getId());
int updated = orderVeneerGoodsMapper.update(
new LambdaUpdateWrapper<OrderVeneerGoodsDO>()
.eq(OrderVeneerGoodsDO::getId, goods.getId())
.eq(OrderVeneerGoodsDO::getVersion, goods.getVersion())
.set(OrderVeneerGoodsDO::getVeneerNum,
statistics == null ? 0 : statistics.getVeneerNum())
.set(OrderVeneerGoodsDO::getPlannedVeneerNum,
statistics == null ? 0 : statistics.getPlannedVeneerNum())
.set(OrderVeneerGoodsDO::getVeneerArea,
statistics == null ? BigDecimal.ZERO : statistics.getVeneerArea())
.set(OrderVeneerGoodsDO::getPlannedVeneerArea,
statistics == null ? BigDecimal.ZERO : statistics.getPlannedVeneerArea())
.set(OrderVeneerGoodsDO::getVersion, goods.getVersion() + 1));
if (updated != 1) {
throw new ServiceException(ORDER_VENEER_GOODS_STATUS_CHANGED);
}
}
}
}
/** 构建一条初始化为零统计值的订单贴皮商品。 */
private OrderVeneerGoodsDO buildOrderVeneerGoods(Long orderId, VeneerDO sourceVeneer,
LoginUser loginUser, LocalDateTime now) {
OrderVeneerGoodsDO goods = OrderVeneerGoodsDO.builder()
.id((Long) identifierGenerator.nextId(null))
.organId(loginUser.getOrganId())
.orderId(orderId)
.sourceVeneerId(sourceVeneer.getId())
.goodsId(sourceVeneer.getVeneerNo())
.goodsName(sourceVeneer.getVeneerName())
.productLevel(sourceVeneer.getProductLevel())
.material(ObjectUtil.defaultIfNull(sourceVeneer.getMaterial(), ""))
.color(ObjectUtil.defaultIfNull(sourceVeneer.getColor(), ""))
.thickness(ObjectUtil.defaultIfNull(sourceVeneer.getThickness(), BigDecimal.ZERO))
.veneerNum(0)
.plannedVeneerNum(0)
.veneerArea(BigDecimal.ZERO)
.plannedVeneerArea(BigDecimal.ZERO)
.version(0)
.build();
goods.setCreateTime(now);
goods.setUpdateTime(now);
goods.setCreator(loginUser.getNickname());
goods.setUpdater(loginUser.getNickname());
goods.setDeleted(false);
return goods;
}
}
@@ -27,6 +27,8 @@ import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.executor.dal.dataobject.ordermodel.OrderModelDO;
import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderPlateVeneerDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsKey;
import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDecomposedPlateCountDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDO;
import com.cf.imes.module.executor.dal.mysql.goods.GoodsMapper;
@@ -111,6 +113,9 @@ public class VeneerDecomposeServiceImpl implements VeneerDecomposeService {
@Resource
private GoodsMapper goodsMapper;
@Resource
private OrderVeneerGoodsService orderVeneerGoodsService;
@Override
public PageResult<VeneerDecomposeOrderRespVO> getOrderPage(VeneerDecomposeOrderPageReqVO req) {
PageDTO<VeneerDecomposeOrderRespVO> page = new PageDTO<>(req.getPageNo(), req.getPageSize());
@@ -328,18 +333,22 @@ public class VeneerDecomposeServiceImpl implements VeneerDecomposeService {
// 从贴皮库加载 A/B 面贴皮,并将贴皮属性以快照形式写入板件贴皮表。
Map<Long, VeneerDO> sourceVeneerMap = loadSourceVeneers(req);
Map<OrderVeneerGoodsKey, OrderVeneerGoodsDO> orderVeneerGoodsMap =
orderVeneerGoodsService.getOrCreate(affectedOrderIds, sourceVeneerMap.values());
List<OrderPlateVeneerDO> plateVeneers = new ArrayList<>();
LoginUser loginUser = Objects.requireNonNull(SecurityFrameworkUtils.getLoginUser());
LocalDateTime createTime = LocalDateTime.now();
for (PlateDO plate : plates) {
if (req.getAVeneerId() != null) {
plateVeneers.add(buildPlateVeneer(
plate, sourceVeneerMap.get(req.getAVeneerId()),
plate,
getOrderVeneerGoodsId(orderVeneerGoodsMap, plate, req.getAVeneerId()),
VeneerSideEnum.A, req.getOuterMargin()));
}
if (req.getBVeneerId() != null) {
plateVeneers.add(buildPlateVeneer(
plate, sourceVeneerMap.get(req.getBVeneerId()),
plate,
getOrderVeneerGoodsId(orderVeneerGoodsMap, plate, req.getBVeneerId()),
VeneerSideEnum.B, req.getOuterMargin()));
}
}
@@ -368,6 +377,12 @@ public class VeneerDecomposeServiceImpl implements VeneerDecomposeService {
}
}
// 明细写入成功后按数据库当前状态重算订单贴皮商品,A/B 面分别计数。
orderVeneerGoodsService.refreshStatistics(plateVeneers.stream()
.map(OrderPlateVeneerDO::getOrderVeneerGoodsId)
.distinct()
.toList());
// 以 order_plate 当前状态重新统计,不使用本次请求数量做增量计算。
List<Long> affectedOrderGoodsIds = plates.stream()
.map(PlateDO::getGoodsId).distinct().sorted().toList();
@@ -515,15 +530,15 @@ public class VeneerDecomposeServiceImpl implements VeneerDecomposeService {
}
/**
* 根据原板件、贴皮逻辑面及贴皮库快照构建一条板件贴皮记录。
* 根据原板件、订单贴皮商品及贴皮逻辑面构建一条板件贴皮记录。
*
* @param plate 原板件
* @param sourceVeneer 选中的贴皮库数据
* @param orderVeneerGoodsId 订单贴皮商品主键
* @param veneerSide 贴皮逻辑面枚举
* @param outerMargin 外扩余量
* @return 待保存的板件贴皮记录
*/
private OrderPlateVeneerDO buildPlateVeneer(PlateDO plate, VeneerDO sourceVeneer,
private OrderPlateVeneerDO buildPlateVeneer(PlateDO plate, Long orderVeneerGoodsId,
VeneerSideEnum veneerSide, BigDecimal outerMargin) {
BigDecimal actualOuterMargin = ObjectUtil.defaultIfNull(outerMargin, BigDecimal.TEN);
BigDecimal sourceLength = plate.getHeight();
@@ -549,6 +564,7 @@ public class VeneerDecomposeServiceImpl implements VeneerDecomposeService {
.organId(plate.getOrganId())
.orderId(plate.getOrderId())
.orderGoodsId(plate.getGoodsId())
.orderVeneerGoodsId(orderVeneerGoodsId)
.orderPlateId(plate.getId())
.plateNo(plate.getPlateNo())
.plateName(plate.getName())
@@ -562,15 +578,23 @@ public class VeneerDecomposeServiceImpl implements VeneerDecomposeService {
.outerMargin(actualOuterMargin)
.veneerArea(veneerArea)
.planId(0L)
.sourceVeneerId(sourceVeneer.getId())
.sourceVeneerNo(sourceVeneer.getVeneerNo())
.veneerName(sourceVeneer.getVeneerName())
.productLevel(sourceVeneer.getProductLevel())
.color(ObjectUtil.defaultIfNull(sourceVeneer.getColor(), ""))
.material(ObjectUtil.defaultIfNull(sourceVeneer.getMaterial(), ""))
.build();
}
/**
* 获取板件当前订单与来源贴皮库商品对应的订单贴皮商品主键。
*/
private Long getOrderVeneerGoodsId(
Map<OrderVeneerGoodsKey, OrderVeneerGoodsDO> orderVeneerGoodsMap,
PlateDO plate, Long sourceVeneerId) {
OrderVeneerGoodsDO orderVeneerGoods = orderVeneerGoodsMap.get(
new OrderVeneerGoodsKey(plate.getOrderId(), sourceVeneerId));
if (orderVeneerGoods == null) {
throw new ServiceException(VENEER_DECOMPOSE_RECORD_INSERT_FAILED);
}
return orderVeneerGoods.getId();
}
/**
* 根据 WebCAD 排版面和贴皮逻辑面确定实际板件面。
* 反面排版时 A 面对应反面、B 面对应正面;正面或随意面排版时关系相反。
@@ -26,6 +26,8 @@ import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerManageResele
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.executor.dal.dataobject.ordermodel.OrderModelDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderPlateVeneerDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsKey;
import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDO;
import com.cf.imes.module.executor.dal.mysql.order.OrderMapper;
import com.cf.imes.module.executor.dal.mysql.veneer.OrderPlateVeneerMapper;
@@ -87,6 +89,9 @@ public class VeneerManageServiceImpl implements VeneerManageService {
@Resource
private VeneerDecomposeService veneerDecomposeService;
@Resource
private OrderVeneerGoodsService orderVeneerGoodsService;
@Resource
private OrderMapper orderMapper;
@@ -112,7 +117,7 @@ public class VeneerManageServiceImpl implements VeneerManageService {
IPage<VeneerManageGoodsRespVO> result = veneerManageMapper.selectGoodsPage(
new PageDTO<>(req.getPageNo(), req.getPageSize()), req);
List<VeneerManageGoodsRespVO> goodsList = result.getRecords();
fillGoodsOrderRelations(goodsList, req, false);
fillGoodsOrderRelations(goodsList, req);
return new PageResult<>(goodsList, result.getTotal());
}
@@ -155,10 +160,10 @@ public class VeneerManageServiceImpl implements VeneerManageService {
@Override
public PageResult<VeneerManageGoodsRespVO> getUnplannedGoodsPage(VeneerManageGoodsPageReqVO req) {
IPage<VeneerManageGoodsRespVO> result = veneerManageMapper.selectUnplannedGoodsPage(
IPage<VeneerManageGoodsRespVO> result = veneerManageMapper.selectGoodsPage(
new PageDTO<>(req.getPageNo(), req.getPageSize()), req);
List<VeneerManageGoodsRespVO> goodsList = result.getRecords();
fillGoodsOrderRelations(goodsList, req, true);
fillGoodsOrderRelations(goodsList, req);
return new PageResult<>(goodsList, result.getTotal());
}
@@ -167,11 +172,9 @@ public class VeneerManageServiceImpl implements VeneerManageService {
*
* @param goodsList 当前页板材分组
* @param req 订单、房间及柜体筛选条件
* @param unplanned 是否使用未排贴皮查询口径
*/
private void fillGoodsOrderRelations(List<VeneerManageGoodsRespVO> goodsList,
VeneerManageGoodsPageReqVO req,
boolean unplanned) {
VeneerManageGoodsPageReqVO req) {
if (CollUtil.isEmpty(goodsList)) {
return;
}
@@ -179,9 +182,8 @@ public class VeneerManageServiceImpl implements VeneerManageService {
.map(VeneerManageGoodsRespVO::getGoodsId)
.distinct()
.toList();
List<VeneerGoodsOrderRelationRespVO> relations = unplanned
? veneerManageMapper.selectUnplannedGoodsOrderRelationList(goodsIds, req)
: veneerManageMapper.selectGoodsOrderRelationList(goodsIds, req);
List<VeneerGoodsOrderRelationRespVO> relations =
veneerManageMapper.selectGoodsOrderRelationList(goodsIds, req);
Map<String, List<VeneerGoodsOrderRelationRespVO>> relationMap = new HashMap<>();
for (VeneerGoodsOrderRelationRespVO relation : relations) {
relationMap.computeIfAbsent(relation.getGoodsId(), key -> new ArrayList<>())
@@ -361,34 +363,50 @@ public class VeneerManageServiceImpl implements VeneerManageService {
throw new ServiceException(VENEER_NOT_EXIST);
}
Set<Long> affectedOrderVeneerGoodsIds = new HashSet<>();
for (List<Long> idBatch : CollUtil.split(ids, RESELECT_BATCH_SIZE)) {
// 仅查询未排单记录;已删除、已排单或状态发生变化时统一按并发冲突处理。
List<OrderPlateVeneerDO> records = orderPlateVeneerMapper.selectList(
new LambdaQueryWrapper<OrderPlateVeneerDO>()
.select(OrderPlateVeneerDO::getId)
.select(OrderPlateVeneerDO::getId,
OrderPlateVeneerDO::getOrderId,
OrderPlateVeneerDO::getOrderVeneerGoodsId)
.eq(OrderPlateVeneerDO::getPlanId, 0L)
.in(OrderPlateVeneerDO::getId, idBatch));
if (records.size() != idBatch.size()) {
throw new ServiceException(VENEER_RESELECT_RECORD_STATUS_CHANGED);
}
// 更新时再次限制未排单状态,避免查询后被其他用户排单仍可重选贴皮。
int updated = orderPlateVeneerMapper.update(
new LambdaUpdateWrapper<OrderPlateVeneerDO>()
.eq(OrderPlateVeneerDO::getPlanId, 0L)
.in(OrderPlateVeneerDO::getId, idBatch)
.set(OrderPlateVeneerDO::getSourceVeneerId, veneer.getId())
.set(OrderPlateVeneerDO::getSourceVeneerNo, veneer.getVeneerNo())
.set(OrderPlateVeneerDO::getVeneerName, veneer.getVeneerName())
.set(OrderPlateVeneerDO::getProductLevel, veneer.getProductLevel())
.set(OrderPlateVeneerDO::getColor,
ObjectUtil.defaultIfNull(veneer.getColor(), ""))
.set(OrderPlateVeneerDO::getMaterial,
ObjectUtil.defaultIfNull(veneer.getMaterial(), "")));
if (updated != idBatch.size()) {
throw new ServiceException(VENEER_RESELECT_RECORD_STATUS_CHANGED);
List<Long> orderIds = records.stream().map(OrderPlateVeneerDO::getOrderId)
.distinct().sorted().toList();
Map<OrderVeneerGoodsKey, OrderVeneerGoodsDO> targetGoodsMap =
orderVeneerGoodsService.getOrCreate(orderIds, List.of(veneer));
Map<Long, List<Long>> targetRecordIds = new HashMap<>();
for (OrderPlateVeneerDO record : records) {
OrderVeneerGoodsDO targetGoods = targetGoodsMap.get(
new OrderVeneerGoodsKey(record.getOrderId(), veneer.getId()));
if (targetGoods == null) {
throw new ServiceException(VENEER_RESELECT_RECORD_STATUS_CHANGED);
}
targetRecordIds.computeIfAbsent(targetGoods.getId(), key -> new ArrayList<>())
.add(record.getId());
affectedOrderVeneerGoodsIds.add(record.getOrderVeneerGoodsId());
affectedOrderVeneerGoodsIds.add(targetGoods.getId());
}
// 按目标订单贴皮商品分组更新,再次限制 plan_id=0 防止并发排单后仍被重选。
for (Map.Entry<Long, List<Long>> entry : targetRecordIds.entrySet()) {
int updated = orderPlateVeneerMapper.update(
new LambdaUpdateWrapper<OrderPlateVeneerDO>()
.eq(OrderPlateVeneerDO::getPlanId, 0L)
.in(OrderPlateVeneerDO::getId, entry.getValue())
.set(OrderPlateVeneerDO::getOrderVeneerGoodsId, entry.getKey()));
if (updated != entry.getValue().size()) {
throw new ServiceException(VENEER_RESELECT_RECORD_STATUS_CHANGED);
}
}
}
orderVeneerGoodsService.refreshStatistics(affectedOrderVeneerGoodsIds);
}
/**
@@ -430,6 +448,10 @@ public class VeneerManageServiceImpl implements VeneerManageService {
List<Long> restoredPlateIds = plateIds.stream()
.filter(plateId -> !remainingPlateIds.contains(plateId))
.toList();
orderVeneerGoodsService.refreshStatistics(selectedRecords.stream()
.map(OrderPlateVeneerDO::getOrderVeneerGoodsId)
.distinct()
.toList());
if (CollUtil.isEmpty(restoredPlateIds)) {
return;
}
@@ -26,18 +26,16 @@ import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerPlanSortReqV
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerPlanSortRespVO;
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerPlanUpdateReqVO;
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerPlanWithdrawProduceReqVO;
import com.cf.imes.module.executor.dal.dataobject.goods.GoodsDO;
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderPlateVeneerDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerPlanDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerPlannedPlateCountDO;
import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerPlanStatisticsDO;
import com.cf.imes.module.executor.dal.mysql.goods.GoodsMapper;
import com.cf.imes.module.executor.dal.mysql.order.OrderMapper;
import com.cf.imes.module.executor.dal.mysql.veneer.OrderVeneerPlanBatchMapper;
import com.cf.imes.module.executor.dal.mysql.veneer.OrderVeneerGoodsMapper;
import com.cf.imes.module.executor.dal.mysql.veneer.VeneerPlanMapper;
import com.cf.imes.module.executor.dal.mysql.veneer.VeneerMapper;
import com.cf.imes.module.executor.enums.VeneerPlanStatusEnum;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
@@ -58,7 +56,6 @@ import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.GOODS_PLATE_UPDATE_CONCURRENCY_ERROR;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_PLATE_UPDATE_CONCURRENCY_ERROR;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_PLAN_AREA_DATA_INVALID;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_PLAN_CREATE_FAILED;
@@ -82,9 +79,7 @@ import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_PLAN_R
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_PLAN_SORT_RECORD_DUPLICATE;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_PLAN_SORT_RECORD_REQUIRED;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_PLAN_SORT_STATUS_CHANGED;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_PLAN_SOURCE_NO_DUPLICATE;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_PLAN_SOURCE_NO_MISMATCH;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_PLAN_SOURCE_NO_NOT_EXIST;
/**
* 贴皮排单 Service 实现。
@@ -137,16 +132,15 @@ public class VeneerPlanServiceImpl implements VeneerPlanService {
private OrderMapper orderMapper;
@Resource
private GoodsMapper goodsMapper;
private OrderVeneerGoodsMapper orderVeneerGoodsMapper;
@Resource
private VeneerMapper veneerMapper;
private OrderVeneerGoodsService orderVeneerGoodsService;
@Override
@Transactional(rollbackFor = Exception.class)
public void createPlan(VeneerPlanCreateReqVO req) {
Map<String, List<Long>> groupIdMap = normalizeGroups(req.getGroups());
Map<String, Long> sourceVeneerIdMap = loadSourceVeneerIdMap(groupIdMap.keySet());
List<Long> veneerIds = groupIdMap.values().stream().flatMap(List::stream).toList();
// 将所有分组ID统一分批查询,避免逐组查询产生N+1,同时控制IN条件长度。
@@ -157,6 +151,8 @@ public class VeneerPlanServiceImpl implements VeneerPlanService {
if (veneers.size() != veneerIds.size()) {
throw new ServiceException(VENEER_PLAN_RECORD_STATUS_CHANGED);
}
Map<Long, OrderVeneerGoodsDO> orderVeneerGoodsMap =
loadOrderVeneerGoodsMap(veneers);
Map<Long, OrderPlateVeneerDO> veneerMap = new HashMap<>(veneers.size());
for (OrderPlateVeneerDO veneer : veneers) {
@@ -171,7 +167,7 @@ public class VeneerPlanServiceImpl implements VeneerPlanService {
// 前端已按贴皮商品编号分组;后端逐组校验归属,并为每个分组创建一个排单。
for (Map.Entry<String, List<Long>> entry : groupIdMap.entrySet()) {
String sourceVeneerNo = entry.getKey();
Long sourceVeneerId = sourceVeneerIdMap.get(sourceVeneerNo);
Long sourceVeneerId = null;
List<Long> groupIds = entry.getValue();
List<OrderPlateVeneerDO> group = new ArrayList<>(groupIds.size());
for (Long veneerId : groupIds) {
@@ -179,7 +175,16 @@ public class VeneerPlanServiceImpl implements VeneerPlanService {
if (veneer == null) {
throw new ServiceException(VENEER_PLAN_RECORD_STATUS_CHANGED);
}
if (!StrUtil.equals(sourceVeneerNo, veneer.getSourceVeneerNo())) {
OrderVeneerGoodsDO orderVeneerGoods =
orderVeneerGoodsMap.get(veneer.getOrderVeneerGoodsId());
if (orderVeneerGoods == null
|| !StrUtil.equals(sourceVeneerNo, orderVeneerGoods.getGoodsId())) {
throw new ServiceException(
VENEER_PLAN_SOURCE_NO_MISMATCH, veneerId, sourceVeneerNo);
}
if (sourceVeneerId == null) {
sourceVeneerId = orderVeneerGoods.getSourceVeneerId();
} else if (!Objects.equals(sourceVeneerId, orderVeneerGoods.getSourceVeneerId())) {
throw new ServiceException(
VENEER_PLAN_SOURCE_NO_MISMATCH, veneerId, sourceVeneerNo);
}
@@ -230,12 +235,11 @@ public class VeneerPlanServiceImpl implements VeneerPlanService {
.distinct()
.sorted()
.toList();
List<Long> affectedOrderGoodsIds = veneers.stream()
.map(OrderPlateVeneerDO::getOrderGoodsId)
refreshOrderPlannedVeneerPlateCount(affectedOrderIds);
orderVeneerGoodsService.refreshStatistics(veneers.stream()
.map(OrderPlateVeneerDO::getOrderVeneerGoodsId)
.distinct()
.sorted()
.toList();
refreshPlannedVeneerPlateCount(affectedOrderIds, affectedOrderGoodsIds);
.toList());
}
/**
@@ -342,8 +346,14 @@ public class VeneerPlanServiceImpl implements VeneerPlanService {
if (veneers.size() != veneerIds.size()) {
throw new ServiceException(VENEER_PLAN_PLATE_STATUS_CHANGED);
}
Map<Long, OrderVeneerGoodsDO> orderVeneerGoodsMap =
loadOrderVeneerGoodsMap(veneers);
for (OrderPlateVeneerDO veneer : veneers) {
if (!Objects.equals(plan.getSourceVeneerId(), veneer.getSourceVeneerId())) {
OrderVeneerGoodsDO orderVeneerGoods =
orderVeneerGoodsMap.get(veneer.getOrderVeneerGoodsId());
if (orderVeneerGoods == null
|| !Objects.equals(plan.getSourceVeneerId(),
orderVeneerGoods.getSourceVeneerId())) {
throw new ServiceException(VENEER_PLAN_PLATE_SOURCE_MISMATCH, veneer.getId());
}
}
@@ -457,7 +467,7 @@ public class VeneerPlanServiceImpl implements VeneerPlanService {
}
}
// 删除前读取受影响范围,恢复贴皮后仍可据此重新统计订单及订单材质数量。
// 删除前读取受影响范围,恢复贴皮后仍可据此重新统计订单及订单贴皮商品数量。
List<OrderPlateVeneerDO> affectedScopes =
veneerPlanMapper.selectPlanAffectedScope(normalizedPlanIds);
int expectedVeneerCount = 0;
@@ -487,12 +497,11 @@ public class VeneerPlanServiceImpl implements VeneerPlanService {
.distinct()
.sorted()
.toList();
List<Long> affectedOrderGoodsIds = affectedScopes.stream()
.map(OrderPlateVeneerDO::getOrderGoodsId)
refreshOrderPlannedVeneerPlateCount(affectedOrderIds);
orderVeneerGoodsService.refreshStatistics(affectedScopes.stream()
.map(OrderPlateVeneerDO::getOrderVeneerGoodsId)
.distinct()
.sorted()
.toList();
refreshPlannedVeneerPlateCount(affectedOrderIds, affectedOrderGoodsIds);
.toList());
}
/**
@@ -690,7 +699,7 @@ public class VeneerPlanServiceImpl implements VeneerPlanService {
}
/**
* 根据本次新增或移除贴皮的归属范围重新统计订单及订单材质数量。
* 根据本次新增或移除贴皮的归属范围重新统计订单及订单贴皮商品数量。
*
* @param veneers 本次操作的板件贴皮记录
*/
@@ -700,56 +709,43 @@ public class VeneerPlanServiceImpl implements VeneerPlanService {
.distinct()
.sorted()
.toList();
List<Long> orderGoodsIds = veneers.stream()
.map(OrderPlateVeneerDO::getOrderGoodsId)
refreshOrderPlannedVeneerPlateCount(orderIds);
orderVeneerGoodsService.refreshStatistics(veneers.stream()
.map(OrderPlateVeneerDO::getOrderVeneerGoodsId)
.distinct()
.toList());
}
/**
* 批量加载板件贴皮关联的订单贴皮商品。
*
* @param veneers 板件贴皮列表
* @return 订单贴皮商品主键与商品数据的映射
*/
private Map<Long, OrderVeneerGoodsDO> loadOrderVeneerGoodsMap(
List<OrderPlateVeneerDO> veneers) {
List<Long> orderVeneerGoodsIds = veneers.stream()
.map(OrderPlateVeneerDO::getOrderVeneerGoodsId)
.filter(Objects::nonNull)
.distinct()
.sorted()
.toList();
refreshPlannedVeneerPlateCount(orderIds, orderGoodsIds);
}
/**
* 按贴皮商品编号批量查询组织内贴皮库主键,并校验编号唯一性和完整性。
*
* @param sourceVeneerNos 本次排单涉及的贴皮商品编号集合
* @return 贴皮商品编号与贴皮库主键的映射
*/
private Map<String, Long> loadSourceVeneerIdMap(Set<String> sourceVeneerNos) {
List<VeneerDO> sourceVeneers = new ArrayList<>();
List<String> sourceVeneerNoList = new ArrayList<>(sourceVeneerNos);
for (List<String> sourceVeneerNoBatch
: CollUtil.split(sourceVeneerNoList, PLAN_BATCH_SIZE)) {
sourceVeneers.addAll(veneerMapper.selectList(
new LambdaQueryWrapper<VeneerDO>()
.select(VeneerDO::getId, VeneerDO::getVeneerNo)
.in(VeneerDO::getVeneerNo, sourceVeneerNoBatch)));
}
Map<String, Long> sourceVeneerIdMap = new HashMap<>(sourceVeneers.size());
for (VeneerDO sourceVeneer : sourceVeneers) {
Long previousId = sourceVeneerIdMap.putIfAbsent(
sourceVeneer.getVeneerNo(), sourceVeneer.getId());
if (previousId != null) {
throw new ServiceException(
VENEER_PLAN_SOURCE_NO_DUPLICATE, sourceVeneer.getVeneerNo());
Map<Long, OrderVeneerGoodsDO> result = new HashMap<>(orderVeneerGoodsIds.size());
for (List<Long> idBatch : CollUtil.split(orderVeneerGoodsIds, PLAN_BATCH_SIZE)) {
List<OrderVeneerGoodsDO> goodsList = orderVeneerGoodsMapper.selectList(
new LambdaQueryWrapper<OrderVeneerGoodsDO>()
.select(OrderVeneerGoodsDO::getId,
OrderVeneerGoodsDO::getSourceVeneerId,
OrderVeneerGoodsDO::getGoodsId)
.in(OrderVeneerGoodsDO::getId, idBatch));
for (OrderVeneerGoodsDO goods : goodsList) {
result.put(goods.getId(), goods);
}
}
for (String sourceVeneerNo : sourceVeneerNos) {
if (!sourceVeneerIdMap.containsKey(sourceVeneerNo)) {
throw new ServiceException(VENEER_PLAN_SOURCE_NO_NOT_EXIST, sourceVeneerNo);
}
if (result.size() != orderVeneerGoodsIds.size()) {
throw new ServiceException(VENEER_PLAN_RECORD_STATUS_CHANGED);
}
return sourceVeneerIdMap;
}
/**
* 根据板件贴皮当前排单状态,重新统计订单和订单材质的已排贴皮板件数量。
*
* @param orderIds 订单ID列表
* @param orderGoodsIds {@code order_goods} 主键列表
*/
private void refreshPlannedVeneerPlateCount(List<Long> orderIds, List<Long> orderGoodsIds) {
refreshOrderPlannedVeneerPlateCount(orderIds);
refreshGoodsPlannedVeneerPlateCount(orderGoodsIds);
return result;
}
/**
@@ -785,39 +781,6 @@ public class VeneerPlanServiceImpl implements VeneerPlanService {
}
}
/**
* 分批重新统计并覆盖订单材质的已排贴皮板件数量,更新时使用 version 进行乐观锁校验。
*
* @param orderGoodsIds {@code order_goods} 主键列表
*/
private void refreshGoodsPlannedVeneerPlateCount(List<Long> orderGoodsIds) {
for (List<Long> orderGoodsIdBatch : CollUtil.split(orderGoodsIds, PLAN_STAT_BATCH_SIZE)) {
Map<Long, GoodsDO> goodsMap = new HashMap<>();
for (GoodsDO goods : goodsMapper.selectByIds(orderGoodsIdBatch)) {
goodsMap.put(goods.getId(), goods);
}
Map<Long, Integer> countMap = convertPlannedVeneerPlateCount(
veneerPlanMapper.selectGoodsPlannedVeneerPlateCount(orderGoodsIdBatch));
for (Long orderGoodsId : orderGoodsIdBatch) {
GoodsDO goods = goodsMap.get(orderGoodsId);
if (goods == null) {
throw new ServiceException(GOODS_PLATE_UPDATE_CONCURRENCY_ERROR, orderGoodsId);
}
int version = goods.getVersion();
int updated = goodsMapper.update(new LambdaUpdateWrapper<GoodsDO>()
.eq(GoodsDO::getId, orderGoodsId)
.eq(GoodsDO::getVersion, version)
.set(GoodsDO::getPlannedVeneerPlateNum,
countMap.getOrDefault(orderGoodsId, 0))
.set(GoodsDO::getVersion, version + 1));
if (updated == 0) {
throw new ServiceException(GOODS_PLATE_UPDATE_CONCURRENCY_ERROR, orderGoodsId);
}
}
}
}
/**
* 将数据库聚合结果转换为目标ID与已排贴皮板件数量的映射。
*
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cf.imes.module.executor.dal.mysql.veneer.OrderVeneerGoodsMapper">
<select id="selectStatistics"
resultType="com.cf.imes.module.executor.dal.dataobject.veneer.OrderVeneerGoodsStatisticsDO">
SELECT opv.order_veneer_goods_id AS orderVeneerGoodsId,
COUNT(*) AS veneerNum,
SUM(CASE WHEN opv.plan_id != 0 THEN 1 ELSE 0 END) AS plannedVeneerNum,
COALESCE(ROUND(SUM(opv.veneer_area), 3), 0) AS veneerArea,
COALESCE(ROUND(SUM(CASE WHEN opv.plan_id != 0 THEN opv.veneer_area ELSE 0 END), 3), 0)
AS plannedVeneerArea
FROM order_plate_veneer opv
WHERE opv.deleted = false
AND opv.order_veneer_goods_id IN
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
GROUP BY opv.order_veneer_goods_id
</select>
</mapper>
@@ -68,13 +68,13 @@
AND EXISTS (
SELECT 1
FROM order_plate_veneer opv
JOIN order_goods og ON og.order_id = opv.order_id
AND og.id = opv.order_goods_id
JOIN order_veneer_goods ovg ON ovg.order_id = opv.order_id
AND ovg.id = opv.order_veneer_goods_id
WHERE opv.order_id = o.id
AND opv.deleted = false
AND opv.plan_id = 0
AND og.deleted = false
AND og.goods_id IN
AND ovg.deleted = false
AND ovg.goods_id IN
<foreach collection="req.goodsIds" item="goodsId" open="(" close=")" separator=",">
#{goodsId}
</foreach>
@@ -145,13 +145,13 @@
AND EXISTS (
SELECT 1
FROM order_plate_veneer opv
JOIN order_goods og ON og.order_id = opv.order_id
AND og.id = opv.order_goods_id
JOIN order_veneer_goods ovg ON ovg.order_id = opv.order_id
AND ovg.id = opv.order_veneer_goods_id
WHERE opv.order_id = o.id
AND opv.deleted = false
AND opv.plan_id = 0
AND og.deleted = false
AND og.goods_id IN
AND ovg.deleted = false
AND ovg.goods_id IN
<foreach collection="req.goodsIds" item="goodsId" open="(" close=")" separator=",">
#{goodsId}
</foreach>
@@ -182,53 +182,63 @@
ORDER BY o.id DESC
</select>
<sql id="PendingVeneerFilter">
AND EXISTS (
SELECT 1
FROM order_plate_veneer opv
WHERE opv.order_id = og.order_id
AND opv.order_goods_id = og.id
AND opv.deleted = false
AND opv.plan_id = 0
<if test="(req.roomIds != null and req.roomIds.size() > 0)
<select id="selectGoodsPage" resultMap="GoodsMap">
SELECT ovg.goods_id AS goodsId,
ovg.goods_name AS goodsName,
ovg.material,
ovg.color,
ovg.thickness,
<choose>
<when test="(req.roomIds != null and req.roomIds.size() > 0)
or (req.bodyIds != null and req.bodyIds.size() > 0)">
AND EXISTS (
SELECT 1 FROM order_item oi
WHERE oi.order_id = opv.order_id
AND oi.plate_id = opv.order_plate_id
AND oi.plate_id != 0
<if test="req.roomIds != null and req.roomIds.size() > 0">
AND oi.room_id IN
<foreach collection="req.roomIds" item="roomId" open="(" close=")" separator=",">
#{roomId}
</foreach>
</if>
<if test="req.bodyIds != null and req.bodyIds.size() > 0">
AND oi.body_id IN
<foreach collection="req.bodyIds" item="bodyId" open="(" close=")" separator=",">
#{bodyId}
</foreach>
</if>
)
</if>
)
</sql>
<sql id="PendingPlateRoomBodyFilter">
COUNT(opv.id) AS num,
COALESCE(ROUND(SUM(opv.veneer_area), 3), 0) AS area
</when>
<otherwise>
SUM(ovg.veneer_num - ovg.planned_veneer_num) AS num,
COALESCE(ROUND(SUM(ovg.veneer_area - ovg.planned_veneer_area), 3), 0) AS area
</otherwise>
</choose>
FROM order_veneer_goods ovg
JOIN orders o ON o.id = ovg.order_id
<if test="(req.roomIds != null and req.roomIds.size() > 0)
or (req.bodyIds != null and req.bodyIds.size() > 0)">
JOIN order_plate_veneer opv ON opv.order_id = ovg.order_id
AND opv.order_veneer_goods_id = ovg.id
AND opv.deleted = false
AND opv.plan_id = 0
</if>
WHERE o.deleted = false
AND o.status IN (1, 2, 3)
AND ovg.deleted = false
AND ovg.veneer_num &gt; ovg.planned_veneer_num
<if test="req.orderIds != null and req.orderIds.size() > 0">
AND ovg.order_id IN
<foreach collection="req.orderIds" item="orderId" open="(" close=")" separator=",">
#{orderId}
</foreach>
</if>
<if test="req.goodsName != null and req.goodsName != ''">
AND ovg.goods_name LIKE CONCAT('%', #{req.goodsName}, '%')
</if>
<if test="req.goodsId != null and req.goodsId != ''">
AND ovg.goods_id LIKE CONCAT('%', #{req.goodsId}, '%')
</if>
<if test="req.material != null and req.material != ''">
AND ovg.material LIKE CONCAT('%', #{req.material}, '%')
</if>
<if test="req.color != null and req.color != ''">
AND ovg.color LIKE CONCAT('%', #{req.color}, '%')
</if>
<if test="req.thickness != null">
AND ovg.thickness = #{req.thickness}
</if>
<if test="(req.roomIds != null and req.roomIds.size() > 0)
or (req.bodyIds != null and req.bodyIds.size() > 0)">
AND EXISTS (
SELECT 1 FROM order_plate_veneer opv
WHERE opv.order_id = op.order_id
AND opv.order_goods_id = og.id
AND opv.order_plate_id = op.id
AND opv.deleted = false
AND opv.plan_id = 0
)
AND EXISTS (
SELECT 1 FROM order_item oi
WHERE oi.order_id = op.order_id
AND oi.plate_id = op.id
WHERE oi.order_id = opv.order_id
AND oi.plate_id = opv.order_plate_id
AND oi.plate_id != 0
<if test="req.roomIds != null and req.roomIds.size() > 0">
AND oi.room_id IN
@@ -244,89 +254,58 @@
</if>
)
</if>
</sql>
<select id="selectGoodsPage" resultMap="GoodsMap">
SELECT og.goods_id AS goodsId,
og.goods_name AS goodsName,
og.material,
og.color,
og.thickness,
<choose>
<when test="(req.roomIds != null and req.roomIds.size() > 0)
or (req.bodyIds != null and req.bodyIds.size() > 0)">
COUNT(op.id) AS num,
SUM(op.area) AS area
</when>
<otherwise>
SUM(og.plate_num) AS num,
SUM(og.area) AS area
</otherwise>
</choose>
FROM orders o
JOIN order_goods og ON og.order_id = o.id
<if test="(req.roomIds != null and req.roomIds.size() > 0)
or (req.bodyIds != null and req.bodyIds.size() > 0)">
JOIN order_plate op ON op.order_id = og.order_id
AND op.goods_id = og.id
AND op.deleted = false
</if>
WHERE o.deleted = false
AND o.status IN (1, 2, 3)
AND og.deleted = false
AND IFNULL(og.decomposed_veneer_plate_num, 0)
&gt; IFNULL(og.planned_veneer_plate_num, 0)
<include refid="PendingVeneerFilter"/>
<include refid="PendingPlateRoomBodyFilter"/>
<if test="req.orderIds != null and req.orderIds.size() > 0">
AND og.order_id IN
<foreach collection="req.orderIds" item="orderId" open="(" close=")" separator=",">
#{orderId}
</foreach>
</if>
<if test="req.goodsName != null and req.goodsName != ''">
AND og.goods_name LIKE CONCAT('%', #{req.goodsName}, '%')
</if>
<if test="req.goodsId != null and req.goodsId != ''">
AND og.goods_id LIKE CONCAT('%', #{req.goodsId}, '%')
</if>
<if test="req.material != null and req.material != ''">
AND og.material LIKE CONCAT('%', #{req.material}, '%')
</if>
<if test="req.color != null and req.color != ''">
AND og.color LIKE CONCAT('%', #{req.color}, '%')
</if>
<if test="req.thickness != null">
AND og.thickness = #{req.thickness}
</if>
GROUP BY og.goods_id, og.goods_name, og.material, og.color, og.thickness
ORDER BY og.thickness DESC
GROUP BY ovg.goods_id, ovg.goods_name, ovg.material, ovg.color, ovg.thickness
ORDER BY ovg.thickness DESC
</select>
<select id="selectGoodsOrderRelationList"
resultType="com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerGoodsOrderRelationRespVO">
SELECT DISTINCT og.goods_id AS goodsId,
og.order_id AS orderId,
og.id AS orderGoodsId
FROM orders o
JOIN order_goods og ON og.order_id = o.id
SELECT DISTINCT ovg.goods_id AS goodsId,
ovg.order_id AS orderId,
ovg.id AS orderVeneerGoodsId
FROM order_veneer_goods ovg
JOIN orders o ON o.id = ovg.order_id
WHERE o.deleted = false
AND o.status IN (1, 2, 3)
AND og.deleted = false
AND IFNULL(og.decomposed_veneer_plate_num, 0)
&gt; IFNULL(og.planned_veneer_plate_num, 0)
<include refid="PendingVeneerFilter"/>
AND og.goods_id IN
AND ovg.deleted = false
AND ovg.veneer_num &gt; ovg.planned_veneer_num
AND ovg.goods_id IN
<foreach collection="goodsIds" item="goodsId" open="(" close=")" separator=",">
#{goodsId}
</foreach>
<if test="req.orderIds != null and req.orderIds.size() > 0">
AND og.order_id IN
AND ovg.order_id IN
<foreach collection="req.orderIds" item="orderId" open="(" close=")" separator=",">
#{orderId}
</foreach>
</if>
ORDER BY og.goods_id, og.order_id
<if test="(req.roomIds != null and req.roomIds.size() > 0)
or (req.bodyIds != null and req.bodyIds.size() > 0)">
AND EXISTS (
SELECT 1
FROM order_plate_veneer opv
JOIN order_item oi ON oi.order_id = opv.order_id
AND oi.plate_id = opv.order_plate_id
AND oi.plate_id != 0
WHERE opv.order_id = ovg.order_id
AND opv.order_veneer_goods_id = ovg.id
AND opv.deleted = false
AND opv.plan_id = 0
<if test="req.roomIds != null and req.roomIds.size() > 0">
AND oi.room_id IN
<foreach collection="req.roomIds" item="roomId" open="(" close=")" separator=",">
#{roomId}
</foreach>
</if>
<if test="req.bodyIds != null and req.bodyIds.size() > 0">
AND oi.body_id IN
<foreach collection="req.bodyIds" item="bodyId" open="(" close=")" separator=",">
#{bodyId}
</foreach>
</if>
)
</if>
ORDER BY ovg.goods_id, ovg.order_id
</select>
<select id="selectUnplannedRootOrderIdList" resultType="java.lang.Long">
@@ -351,13 +330,13 @@
AND EXISTS (
SELECT 1
FROM order_plate_veneer opv
JOIN order_goods og ON og.order_id = opv.order_id
AND og.id = opv.order_goods_id
JOIN order_veneer_goods ovg ON ovg.order_id = opv.order_id
AND ovg.id = opv.order_veneer_goods_id
WHERE opv.order_id = o.id
AND opv.deleted = false
AND opv.plan_id = 0
AND og.deleted = false
AND og.goods_id IN
AND ovg.deleted = false
AND ovg.goods_id IN
<foreach collection="req.goodsIds" item="goodsId" open="(" close=")" separator=",">
#{goodsId}
</foreach>
@@ -385,87 +364,6 @@
ORDER BY o.root_id DESC
</select>
<select id="selectUnplannedGoodsPage" resultMap="GoodsMap">
SELECT og.goods_id AS goodsId,
og.goods_name AS goodsName,
og.material,
og.color,
og.thickness,
<choose>
<when test="(req.roomIds != null and req.roomIds.size() > 0)
or (req.bodyIds != null and req.bodyIds.size() > 0)">
COUNT(op.id) AS num,
SUM(op.area) AS area
</when>
<otherwise>
SUM(og.plate_num) AS num,
SUM(og.area) AS area
</otherwise>
</choose>
FROM orders o
JOIN order_goods og ON og.order_id = o.id
<if test="(req.roomIds != null and req.roomIds.size() > 0)
or (req.bodyIds != null and req.bodyIds.size() > 0)">
JOIN order_plate op ON op.order_id = og.order_id
AND op.goods_id = og.id
AND op.deleted = false
</if>
WHERE o.deleted = false
AND o.status IN (1, 2, 3)
AND og.deleted = false
AND IFNULL(og.plate_num, 0) &gt; IFNULL(og.planned_veneer_plate_num, 0)
<include refid="PendingVeneerFilter"/>
<include refid="PendingPlateRoomBodyFilter"/>
<if test="req.orderIds != null and req.orderIds.size() > 0">
AND og.order_id IN
<foreach collection="req.orderIds" item="orderId" open="(" close=")" separator=",">
#{orderId}
</foreach>
</if>
<if test="req.goodsName != null and req.goodsName != ''">
AND og.goods_name LIKE CONCAT('%', #{req.goodsName}, '%')
</if>
<if test="req.goodsId != null and req.goodsId != ''">
AND og.goods_id LIKE CONCAT('%', #{req.goodsId}, '%')
</if>
<if test="req.material != null and req.material != ''">
AND og.material LIKE CONCAT('%', #{req.material}, '%')
</if>
<if test="req.color != null and req.color != ''">
AND og.color LIKE CONCAT('%', #{req.color}, '%')
</if>
<if test="req.thickness != null">
AND og.thickness = #{req.thickness}
</if>
GROUP BY og.goods_id, og.goods_name, og.material, og.color, og.thickness
ORDER BY og.thickness DESC
</select>
<select id="selectUnplannedGoodsOrderRelationList"
resultType="com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerGoodsOrderRelationRespVO">
SELECT DISTINCT og.goods_id AS goodsId,
og.order_id AS orderId,
og.id AS orderGoodsId
FROM orders o
JOIN order_goods og ON og.order_id = o.id
WHERE o.deleted = false
AND o.status IN (1, 2, 3)
AND og.deleted = false
AND IFNULL(og.plate_num, 0) &gt; IFNULL(og.planned_veneer_plate_num, 0)
<include refid="PendingVeneerFilter"/>
AND og.goods_id IN
<foreach collection="goodsIds" item="goodsId" open="(" close=")" separator=",">
#{goodsId}
</foreach>
<if test="req.orderIds != null and req.orderIds.size() > 0">
AND og.order_id IN
<foreach collection="req.orderIds" item="orderId" open="(" close=")" separator=",">
#{orderId}
</foreach>
</if>
ORDER BY og.goods_id, og.order_id
</select>
<select id="selectUnplannedOrderChildList" resultMap="OrderMap">
SELECT o.id AS orderId,
o.parent_id AS parentId,
@@ -500,13 +398,13 @@
AND EXISTS (
SELECT 1
FROM order_plate_veneer opv
JOIN order_goods og ON og.order_id = opv.order_id
AND og.id = opv.order_goods_id
JOIN order_veneer_goods ovg ON ovg.order_id = opv.order_id
AND ovg.id = opv.order_veneer_goods_id
WHERE opv.order_id = o.id
AND opv.deleted = false
AND opv.plan_id = 0
AND og.deleted = false
AND og.goods_id IN
AND ovg.deleted = false
AND ovg.goods_id IN
<foreach collection="req.goodsIds" item="goodsId" open="(" close=")" separator=",">
#{goodsId}
</foreach>
@@ -542,28 +440,28 @@
opv.plate_width AS width,
opv.plate_thickness AS thickness,
opv.plan_id AS planId,
opv.source_veneer_no AS sourceVeneerNo,
opv.veneer_name AS veneerName,
opv.product_level AS productLevel,
opv.color,
opv.material
ovg.goods_id AS sourceVeneerNo,
ovg.goods_name AS veneerName,
ovg.product_level AS productLevel,
ovg.color,
ovg.material
</sql>
<select id="selectOrderPlateList" resultMap="PlateVeneerMap">
SELECT
<include refid="PlateVeneerColumns"/>
FROM order_plate_veneer opv
JOIN order_goods og ON og.order_id = opv.order_id
AND og.id = opv.order_goods_id
JOIN order_veneer_goods ovg ON ovg.order_id = opv.order_id
AND ovg.id = opv.order_veneer_goods_id
WHERE opv.deleted = false
AND opv.plan_id = 0
AND og.deleted = false
AND ovg.deleted = false
AND opv.order_id IN
<foreach collection="req.orderIds" item="orderId" open="(" close=")" separator=",">
#{orderId}
</foreach>
<if test="req.goodsIds != null and req.goodsIds.size() > 0">
AND og.goods_id IN
AND ovg.goods_id IN
<foreach collection="req.goodsIds" item="goodsId" open="(" close=")" separator=",">
#{goodsId}
</foreach>
@@ -597,12 +495,12 @@
SELECT
<include refid="PlateVeneerColumns"/>
FROM order_plate_veneer opv
JOIN order_goods og ON og.order_id = opv.order_id
AND og.id = opv.order_goods_id
JOIN order_veneer_goods ovg ON ovg.order_id = opv.order_id
AND ovg.id = opv.order_veneer_goods_id
WHERE opv.deleted = false
AND opv.plan_id = 0
AND og.deleted = false
AND og.goods_id IN
AND ovg.deleted = false
AND ovg.goods_id IN
<foreach collection="req.goodsIds" item="goodsId" open="(" close=")" separator=",">
#{goodsId}
</foreach>
@@ -640,16 +538,17 @@
opv.id,
opv.order_id AS orderId,
opv.order_goods_id AS orderGoodsId,
opv.order_veneer_goods_id AS orderVeneerGoodsId,
opv.veneer_side AS veneerSide,
opv.plate_surface AS plateSurface,
opv.veneer_no AS veneerNo,
opv.outer_margin AS outerMargin,
opv.source_veneer_id AS sourceVeneerId,
opv.source_veneer_no AS sourceVeneerNo,
opv.veneer_name AS veneerName,
opv.product_level AS productLevel,
opv.color AS veneerColor,
opv.material AS veneerMaterial,
ovg.source_veneer_id AS sourceVeneerId,
ovg.goods_id AS sourceVeneerNo,
ovg.goods_name AS veneerName,
ovg.product_level AS productLevel,
ovg.color AS veneerColor,
ovg.material AS veneerMaterial,
op.id AS plateId,
og.goods_id AS goodsId,
og.goods_name AS goodsName,
@@ -722,6 +621,8 @@
JOIN order_goods og ON og.order_id = opv.order_id
AND og.id = opv.order_goods_id
AND og.id = op.goods_id
JOIN order_veneer_goods ovg ON ovg.order_id = opv.order_id
AND ovg.id = opv.order_veneer_goods_id
JOIN order_item oi ON oi.order_id = op.order_id
AND oi.plate_id = op.id
AND oi.plate_id != 0
@@ -731,6 +632,7 @@
AND opv.plan_id = 0
AND op.deleted = false
AND og.deleted = false
AND ovg.deleted = false
<if test="req.orderIds != null and req.orderIds.size() > 0">
AND opv.order_id IN
<foreach collection="req.orderIds" item="orderId" open="(" close=")" separator=",">
@@ -738,7 +640,7 @@
</foreach>
</if>
<if test="req.goodsIds != null and req.goodsIds.size() > 0">
AND og.goods_id IN
AND ovg.goods_id IN
<foreach collection="req.goodsIds" item="goodsId" open="(" close=")" separator=",">
#{goodsId}
</foreach>
@@ -750,13 +652,13 @@
AND opv.plate_no LIKE CONCAT('%', #{req.plateNo}, '%')
</if>
<if test="req.sourceVeneerNo != null and req.sourceVeneerNo != ''">
AND opv.source_veneer_no LIKE CONCAT('%', #{req.sourceVeneerNo}, '%')
AND ovg.goods_id LIKE CONCAT('%', #{req.sourceVeneerNo}, '%')
</if>
<if test="req.material != null and req.material != ''">
AND opv.material LIKE CONCAT('%', #{req.material}, '%')
AND ovg.material LIKE CONCAT('%', #{req.material}, '%')
</if>
<if test="req.color != null and req.color != ''">
AND opv.color LIKE CONCAT('%', #{req.color}, '%')
AND ovg.color LIKE CONCAT('%', #{req.color}, '%')
</if>
<if test="req.plateName != null and req.plateName != ''">
AND opv.plate_name LIKE CONCAT('%', #{req.plateName}, '%')
@@ -790,6 +692,7 @@
SELECT opv.id,
opv.order_id AS orderId,
opv.order_goods_id AS orderGoodsId,
opv.order_veneer_goods_id AS orderVeneerGoodsId,
opv.order_plate_id AS orderPlateId
FROM order_plate_veneer opv
WHERE opv.deleted = true
@@ -89,8 +89,9 @@
SELECT opv.id,
opv.order_id AS orderId,
opv.order_goods_id AS orderGoodsId,
opv.order_veneer_goods_id AS orderVeneerGoodsId,
opv.order_plate_id AS orderPlateId,
opv.source_veneer_id AS sourceVeneerId
opv.plan_id AS planId
FROM order_plate_veneer opv
WHERE opv.deleted = false
AND opv.plan_id = #{planId}
@@ -146,12 +147,15 @@
opv.plate_length AS length,
opv.plate_width AS width,
opv.plate_thickness AS thickness,
opv.source_veneer_no AS sourceVeneerNo,
opv.veneer_name AS veneerName,
opv.product_level AS productLevel,
opv.color,
opv.material
ovg.goods_id AS sourceVeneerNo,
ovg.goods_name AS veneerName,
ovg.product_level AS productLevel,
ovg.color,
ovg.material
FROM order_plate_veneer opv
JOIN order_veneer_goods ovg ON ovg.order_id = opv.order_id
AND ovg.id = opv.order_veneer_goods_id
AND ovg.deleted = false
WHERE opv.deleted = false
AND opv.plan_id = #{planId}
ORDER BY opv.order_plate_id DESC, opv.veneer_side
@@ -163,11 +167,10 @@
opv.organ_id AS organId,
opv.order_id AS orderId,
opv.order_goods_id AS orderGoodsId,
opv.order_veneer_goods_id AS orderVeneerGoodsId,
opv.order_plate_id AS orderPlateId,
opv.plate_no AS plateNo,
opv.veneer_area AS veneerArea,
opv.source_veneer_id AS sourceVeneerId,
opv.source_veneer_no AS sourceVeneerNo
opv.veneer_area AS veneerArea
FROM order_plate_veneer opv
WHERE opv.deleted = false
AND opv.plan_id = 0
@@ -212,33 +215,10 @@
GROUP BY opv.order_id
</select>
<select id="selectGoodsPlannedVeneerPlateCount"
resultType="com.cf.imes.module.executor.dal.dataobject.veneer.VeneerPlannedPlateCountDO">
SELECT opv.order_goods_id AS targetId,
COUNT(DISTINCT opv.order_plate_id) AS plannedVeneerPlateNum
FROM order_plate_veneer opv
WHERE opv.deleted = false
AND opv.plan_id != 0
AND opv.order_goods_id IN
<foreach collection="orderGoodsIds" item="orderGoodsId" open="(" close=")" separator=",">
#{orderGoodsId}
</foreach>
AND NOT EXISTS (
SELECT 1
FROM order_plate_veneer pending
WHERE pending.order_id = opv.order_id
AND pending.order_goods_id = opv.order_goods_id
AND pending.order_plate_id = opv.order_plate_id
AND pending.deleted = false
AND pending.plan_id = 0
)
GROUP BY opv.order_goods_id
</select>
<select id="selectPlanAffectedScope"
resultType="com.cf.imes.module.executor.dal.dataobject.veneer.OrderPlateVeneerDO">
SELECT DISTINCT opv.order_id AS orderId,
opv.order_goods_id AS orderGoodsId
opv.order_veneer_goods_id AS orderVeneerGoodsId
FROM order_plate_veneer opv
WHERE opv.deleted = false
AND opv.plan_id IN
@@ -78,6 +78,8 @@ veneer.decompose.plate.size.invalid=板件{0}的長寬或外擴餘量異常,
veneer.decompose.mode.required=請選擇貼皮分解模式
veneer.decompose.order.ids.required=按訂單分解時,訂單ID列表不能為空
veneer.decompose.goods.ids.required=按材質分解時,板材商品編碼列表不能為空
order.veneer.goods.create.failed=訂單貼皮商品建立失敗,請重新整理後重試
order.veneer.goods.status.changed=訂單貼皮商品狀態已變更,請重新整理後重試
veneer.decompose.plate.no.required=板件編號不能為空
veneer.decompose.outer.margin.min=外擴餘量不能小於0
veneer.reselect.record.required=請選擇需要重選貼皮的資料
@@ -78,6 +78,8 @@ veneer.decompose.plate.size.invalid=Plate {0} has invalid dimensions or outer ma
veneer.decompose.mode.required=Please select a veneer decomposition mode
veneer.decompose.order.ids.required=Order ID list is required when decomposing by order
veneer.decompose.goods.ids.required=Goods code list is required when decomposing by material
order.veneer.goods.create.failed=Failed to create order veneer goods. Please refresh and try again
order.veneer.goods.status.changed=Order veneer goods status has changed. Please refresh and try again
veneer.decompose.plate.no.required=Plate numbers cannot be empty
veneer.decompose.outer.margin.min=Outer margin cannot be less than 0
veneer.reselect.record.required=Please select records for veneer reselection
@@ -78,6 +78,8 @@ veneer.decompose.plate.size.invalid=板件{0}的长宽或外扩余量异常,
veneer.decompose.mode.required=请选择贴皮分解模式
veneer.decompose.order.ids.required=按订单分解时,订单ID列表不能为空
veneer.decompose.goods.ids.required=按材质分解时,板材商品编码列表不能为空
order.veneer.goods.create.failed=订单贴皮商品创建失败,请刷新后重试
order.veneer.goods.status.changed=订单贴皮商品状态已变更,请刷新后重试
veneer.decompose.plate.no.required=板件编号不能为空
veneer.decompose.outer.margin.min=外扩余量不能小于0
veneer.reselect.record.required=请选择需要重选贴皮的数据