Commit 5915dd5300fcecabc3c344ec94ed78d98075b6c6

Authored by yeqianyong
1 parent 604d908d

楚江ERP-生成发货单接口开发

... ... @@ -38,6 +38,12 @@ public class PurchaseOrderInfo extends BaseEntity implements BaseDto {
38 38 private String contractId;
39 39
40 40 /**
  41 + * 合同类型
  42 + */
  43 + @TableField(exist = false)
  44 + private String contractType;
  45 +
  46 + /**
41 47 * 订单编号
42 48 */
43 49 private String orderNo;
... ... @@ -74,6 +80,12 @@ public class PurchaseOrderInfo extends BaseEntity implements BaseDto {
74 80 private String deliveryMethod;
75 81
76 82 /**
  83 + * 目的地
  84 + */
  85 + @TableField(exist = false)
  86 + private String destination;
  87 +
  88 + /**
77 89 * 价格表编号
78 90 */
79 91 private String priceListNo;
... ...
... ... @@ -74,7 +74,7 @@ public class ShipmentsOrderInfo extends BaseEntity implements BaseDto {
74 74 private String deptName;
75 75
76 76 /**
77   - * 交货方式
  77 + * 交货/运输方式
78 78 */
79 79 private String deliveryType;
80 80
... ... @@ -84,6 +84,11 @@ public class ShipmentsOrderInfo extends BaseEntity implements BaseDto {
84 84 private String destination;
85 85
86 86 /**
  87 + * 付款方式
  88 + */
  89 + private String paymentType;
  90 +
  91 + /**
87 92 * 实发数量
88 93 */
89 94 private Double actualShipmentQuantity;
... ...
... ... @@ -64,19 +64,6 @@ public class ShipmentsPlanDetail extends BaseEntity implements BaseDto {
64 64 private String contractType;
65 65
66 66 /**
67   - * 交货方式
68   - */
69   - @TableField(exist = false)
70   - private String deliveryMethod;
71   -
72   -
73   - /**
74   - * 结算方式或期限
75   - */
76   - @TableField(exist = false)
77   - private String settlementTerms;
78   -
79   - /**
80 67 * 客户ID
81 68 */
82 69 @TableField(exist = false)
... ...
... ... @@ -23,10 +23,12 @@ import com.lframework.starter.common.utils.Assert;
23 23 import com.lframework.starter.web.inner.components.oplog.OtherOpLogType;
24 24 import com.lframework.xingyun.basedata.entity.Workshop;
25 25 import com.lframework.xingyun.basedata.service.workshop.WorkshopService;
  26 +import com.lframework.xingyun.sc.entity.ContractDistributorStandard;
26 27 import com.lframework.xingyun.sc.entity.CustomerCredit;
27 28 import com.lframework.xingyun.sc.entity.PurchaseOrderInfo;
28 29 import com.lframework.xingyun.sc.enums.OrderSpecChangeStatus;
29 30 import com.lframework.xingyun.sc.mappers.PurchaseOrderInfoMapper;
  31 +import com.lframework.xingyun.sc.service.contract.ContractDistributorStandardService;
30 32 import com.lframework.xingyun.sc.service.customer.CustomerCreditService;
31 33 import com.lframework.xingyun.sc.service.order.PurchaseOrderInfoService;
32 34 import com.lframework.xingyun.sc.service.order.PurchaseOrderLineService;
... ... @@ -40,6 +42,7 @@ import org.springframework.stereotype.Service;
40 42 import javax.annotation.Resource;
41 43 import java.math.BigDecimal;
42 44 import java.util.*;
  45 +import java.util.function.Function;
43 46 import java.util.stream.Collectors;
44 47
45 48 @Service
... ... @@ -56,6 +59,8 @@ public class PurchaseOrderInfoServiceImpl extends BaseMpServiceImpl<PurchaseOrde
56 59 private FlowTaskWrapperMapper flowTaskWrapperMapper;
57 60 @Resource
58 61 private WorkshopService workshopService;
  62 + @Resource
  63 + private ContractDistributorStandardService contractDistributorStandardService;
59 64
60 65 @Override
61 66 public PageResult<PurchaseOrderInfo> query(Integer pageIndex, Integer pageSize, QueryPurchaseOrderInfoVo vo) {
... ... @@ -461,6 +466,36 @@ public class PurchaseOrderInfoServiceImpl extends BaseMpServiceImpl<PurchaseOrde
461 466 }
462 467
463 468 @Override
  469 + public List<PurchaseOrderInfo> queryByIds(List<String> ids) {
  470 + if (CollectionUtils.isEmpty(ids)) {
  471 + return Collections.emptyList();
  472 + }
  473 + List<PurchaseOrderInfo> orderInfoList = getBaseMapper().queryByIds(ids);
  474 + if (CollectionUtils.isEmpty(orderInfoList)) {
  475 + return Collections.emptyList();
  476 + }
  477 + // 获取合同数据
  478 + List<String> contractIds = orderInfoList.stream().map(PurchaseOrderInfo::getContractId).collect(Collectors.toList());
  479 + if (CollectionUtils.isEmpty(contractIds)) {
  480 + return orderInfoList;
  481 + }
  482 + List<ContractDistributorStandard> contractList = contractDistributorStandardService.listByIds(contractIds);
  483 + if (CollectionUtils.isEmpty(contractList)) {
  484 + return orderInfoList;
  485 + }
  486 + Map<String, ContractDistributorStandard> contractMap = contractList.stream().collect(Collectors.toMap(ContractDistributorStandard::getId, Function.identity()));
  487 + for (PurchaseOrderInfo orderInfo : orderInfoList) {
  488 + String contractId = orderInfo.getContractId();
  489 + ContractDistributorStandard contract = contractMap.get(contractId);
  490 + if (contract == null) {
  491 + continue;
  492 + }
  493 + orderInfo.setDestination(contract.getDestination());
  494 + }
  495 + return Collections.emptyList();
  496 + }
  497 +
  498 + @Override
464 499 public void cleanCacheByKey(Serializable key) {
465 500
466 501 }
... ...
... ... @@ -3,13 +3,17 @@ package com.lframework.xingyun.sc.impl.shipments;
3 3 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
4 4 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
5 5 import com.github.pagehelper.PageInfo;
  6 +import com.lframework.starter.web.core.components.security.SecurityUtil;
6 7 import com.lframework.starter.web.core.utils.*;
  8 +import com.lframework.starter.web.inner.dto.dic.city.DicCityDto;
7 9 import com.lframework.starter.web.inner.entity.SysDept;
  10 +import com.lframework.starter.web.inner.service.DicCityService;
8 11 import com.lframework.starter.web.inner.service.system.SysDeptService;
9 12 import com.lframework.xingyun.basedata.entity.Customer;
10 13 import com.lframework.xingyun.basedata.entity.Workshop;
11 14 import com.lframework.xingyun.basedata.service.customer.CustomerService;
12 15 import com.lframework.xingyun.basedata.service.workshop.WorkshopService;
  16 +import com.lframework.xingyun.sc.entity.PurchaseOrderInfo;
13 17 import com.lframework.xingyun.sc.entity.ShipmentsOrderInfo;
14 18 import com.lframework.starter.web.core.impl.BaseMpServiceImpl;
15 19 import com.lframework.starter.web.core.components.resp.PageResult;
... ... @@ -20,9 +24,12 @@ import com.lframework.starter.common.utils.Assert;
20 24 import com.lframework.starter.web.inner.components.oplog.OtherOpLogType;
21 25 import com.lframework.xingyun.sc.entity.ShipmentsPlan;
22 26 import com.lframework.xingyun.sc.entity.ShipmentsPlanDetail;
  27 +import com.lframework.xingyun.sc.service.order.PurchaseOrderInfoService;
23 28 import com.lframework.xingyun.sc.service.shipments.ShipmentsPlanDetailService;
24 29 import com.lframework.xingyun.sc.service.shipments.ShipmentsPlanService;
  30 +import com.lframework.xingyun.sc.utils.CommonUtil;
25 31 import com.lframework.xingyun.sc.vo.shipments.order.GenerateShipmentsOrderVo;
  32 +import lombok.extern.slf4j.Slf4j;
26 33 import org.apache.commons.collections4.CollectionUtils;
27 34 import org.apache.commons.lang3.StringUtils;
28 35 import org.springframework.transaction.annotation.Transactional;
... ... @@ -39,6 +46,7 @@ import java.util.function.Function;
39 46 import java.util.stream.Collectors;
40 47
41 48 @Service
  49 +@Slf4j
42 50 public class ShipmentsOrderInfoServiceImpl extends BaseMpServiceImpl<ShipmentsOrderInfoMapper, ShipmentsOrderInfo> implements ShipmentsOrderInfoService {
43 51
44 52
... ... @@ -49,6 +57,10 @@ public class ShipmentsOrderInfoServiceImpl extends BaseMpServiceImpl<ShipmentsOr
49 57 private ShipmentsPlanDetailService shipmentsPlanDetailService;
50 58 @Resource
51 59 private ShipmentsPlanService shipmentsPlanService;
  60 + @Resource
  61 + private DicCityService dicCityService;
  62 + @Resource
  63 + private PurchaseOrderInfoService purchaseOrderInfoService;
52 64
53 65
54 66 @Override
... ... @@ -206,7 +218,22 @@ public class ShipmentsOrderInfoServiceImpl extends BaseMpServiceImpl<ShipmentsOr
206 218 String type = vo.getType();
207 219 if ("AUTO".equals(type)) {
208 220 // 根据客户批量生成
209   -
  221 + List<ShipmentsPlanDetail> detailList = shipmentsPlanDetailService.listByPlanId(planId);
  222 + if (CollectionUtils.isEmpty(detailList)) {
  223 + return;
  224 + }
  225 + // 根据客户分组
  226 + Map<String, List<ShipmentsPlanDetail>> detailMap = new HashMap<>();
  227 + for (ShipmentsPlanDetail detail : detailList) {
  228 + List<ShipmentsPlanDetail> list = detailMap.computeIfAbsent(detail.getCustomerId(), k -> new ArrayList<>());
  229 + list.add(detail);
  230 + }
  231 + // todo 如果客户很多,则此处需要优化
  232 + for (Map.Entry<String, List<ShipmentsPlanDetail>> entry : detailMap.entrySet()) {
  233 + List<ShipmentsPlanDetail> value = entry.getValue();
  234 + List<List<ShipmentsPlanDetail>> batchList = CommonUtil.partition(value, 8);
  235 + handleBatchData(batchList, planId);
  236 + }
210 237 } else {
211 238 List<String> planDetailIds = vo.getPlanDetailIds();
212 239 if (CollectionUtils.isEmpty(planDetailIds)) {
... ... @@ -216,19 +243,93 @@ public class ShipmentsOrderInfoServiceImpl extends BaseMpServiceImpl<ShipmentsOr
216 243 if (CollectionUtils.isEmpty(detailList)) {
217 244 throw new DefaultClientException("发货明细数据不存在!");
218 245 }
  246 + List<List<ShipmentsPlanDetail>> batchList = CommonUtil.partition(detailList, 8);
  247 + handleBatchData(batchList, planId);
  248 + }
  249 + }
  250 +
  251 +
  252 + @Override
  253 + public void batchAdd(List<ShipmentsOrderInfo> orderInfos) {
  254 + if (CollectionUtils.isEmpty(orderInfos)) {
  255 + return;
  256 + }
  257 + getBaseMapper().batchAdd(orderInfos);
  258 + }
  259 +
  260 +
  261 + /**
  262 + * 处理批次数据
  263 + *
  264 + * @param batchList 数据批次
  265 + */
  266 + private void handleBatchData(List<List<ShipmentsPlanDetail>> batchList, String planId) {
  267 + if (CollectionUtils.isEmpty(batchList)) {
  268 + return;
  269 + }
  270 + // 获取发货计划数据
  271 + ShipmentsPlan plan = shipmentsPlanService.findById(planId);
  272 + // 获取所有城市数据
  273 + List<DicCityDto> allCity = dicCityService.getAll();
  274 + // 获取所有订货单数据
  275 + List<String> orderIds = batchList.stream().flatMap(List::stream).map(ShipmentsPlanDetail::getOrderId)
  276 + .filter(Objects::nonNull)
  277 + .distinct()
  278 + .collect(Collectors.toList());
  279 + List<PurchaseOrderInfo> orderInfoList = purchaseOrderInfoService.queryByIds(orderIds);
  280 + Map<String, PurchaseOrderInfo> orderInfoMap = new HashMap<>();
  281 + if (CollectionUtils.isEmpty(orderInfoList)) {
  282 + orderInfoMap = orderInfoList.stream().collect(Collectors.toMap(PurchaseOrderInfo::getId, Function.identity()));
  283 + }
  284 + Map<String, List<String>> deptIdMap = new HashMap<>();
  285 + List<String> detailIds = new ArrayList<>();
  286 + List<ShipmentsOrderInfo> shipmentsOrderInfoList = new ArrayList<>();
  287 + for (List<ShipmentsPlanDetail> details : batchList) {
219 288 String id = IdUtil.getId();
220   - String customerId = detailList.get(0).getCustomerId();
  289 + String customerId = details.get(0).getCustomerId();
221 290 StringBuilder deliveryTypeBuilder = new StringBuilder();
222 291 StringBuilder destinationBuilder = new StringBuilder();
223   - // 获取城市数据
224   -
225   - for (ShipmentsPlanDetail detail : detailList) {
  292 + StringBuilder paymentTypeBuilder = new StringBuilder();
  293 + Set<String> deliveryTypeSet = new HashSet<>();
  294 + Set<String> destinationSet = new HashSet<>();
  295 + Set<String> paymentTypeSet = new HashSet<>();
  296 + for (ShipmentsPlanDetail detail : details) {
226 297 if (!customerId.equals(detail.getCustomerId())) {
227 298 throw new DefaultClientException("只能选择同一客户下的数据!");
228 299 }
229 300 detail.setShipmentOrderId(id);
  301 + detailIds.add(detail.getId());
230 302
231   - deliveryTypeBuilder.append(detail.getDeliveryMethod()).append(",");
  303 + PurchaseOrderInfo orderInfo = orderInfoMap.get(detail.getOrderId());
  304 + if (orderInfo == null) {
  305 + continue;
  306 + }
  307 + // 办事处
  308 + List<String> list = deptIdMap.computeIfAbsent(id, k -> new ArrayList<>());
  309 + if (list.contains(orderInfo.getDeptId())) {
  310 + list.add(orderInfo.getDeptId());
  311 + }
  312 + // 交货方式
  313 + String deliveryMethod = orderInfo.getDeliveryMethod();
  314 + if (StringUtils.isNotBlank(deliveryMethod) && !deliveryTypeSet.contains(deliveryMethod)) {
  315 + deliveryTypeSet.add(deliveryMethod);
  316 + deliveryTypeBuilder.append(deliveryMethod).append(",");
  317 + }
  318 + // 付款方式
  319 + String paymentType = orderInfo.getSettlementTerms();
  320 + if (StringUtils.isNotBlank(paymentType) && !paymentTypeSet.contains(paymentType)) {
  321 + paymentTypeSet.add(paymentType);
  322 + paymentTypeBuilder.append(paymentType).append(",");
  323 + }
  324 + // 目的地
  325 + String destination = orderInfo.getDestination();
  326 + if (StringUtils.isNotBlank(destination) && !destinationSet.contains(destination)) {
  327 + destinationSet.add(destination);
  328 + List<DicCityDto> fullPath = dicCityService.getFullPath(destination, allCity);
  329 + for (DicCityDto cityDto : fullPath) {
  330 + destinationBuilder.append(cityDto.getName()).append(",");
  331 + }
  332 + }
232 333 }
233 334 if (deliveryTypeBuilder.length() > 0) {
234 335 deliveryTypeBuilder.setLength(deliveryTypeBuilder.length() - 1);
... ... @@ -236,22 +337,37 @@ public class ShipmentsOrderInfoServiceImpl extends BaseMpServiceImpl<ShipmentsOr
236 337 if (destinationBuilder.length() > 0) {
237 338 destinationBuilder.setLength(destinationBuilder.length() - 1);
238 339 }
239   - // 获取发货计划数据
240   - ShipmentsPlan plan = shipmentsPlanService.findById(planId);
  340 + if (paymentTypeBuilder.length() > 0) {
  341 + paymentTypeBuilder.setLength(paymentTypeBuilder.length() - 1);
  342 + }
241 343 // 封装发货单数据
242   - CreateShipmentsOrderInfoVo createVo = new CreateShipmentsOrderInfoVo();
243   - createVo.setPlanId(planId);
244   - createVo.setCustomerId(customerId);
245   - createVo.setWorkshopId(plan.getWorkshopId());
246   - createVo.setShipmentsDate(plan.getTomoPreShipDate());
247   - createVo.setDeliveryType(deliveryTypeBuilder.toString());
248   - createVo.setDestination(destinationBuilder.toString());
  344 + ShipmentsOrderInfo shipmentsOrderInfo = new ShipmentsOrderInfo();
  345 + shipmentsOrderInfo.setId(id);
  346 + shipmentsOrderInfo.setPlanId(planId);
  347 + shipmentsOrderInfo.setCustomerId(customerId);
  348 + shipmentsOrderInfo.setWorkshopId(plan.getWorkshopId());
  349 + shipmentsOrderInfo.setShipmentsDate(plan.getTomoPreShipDate());
  350 + shipmentsOrderInfo.setDeliveryType(deliveryTypeBuilder.toString());
  351 + shipmentsOrderInfo.setDestination(destinationBuilder.toString());
  352 + shipmentsOrderInfo.setPaymentType(paymentTypeBuilder.toString());
  353 + shipmentsOrderInfo.setStatus("UN_SHIPMENTS");
  354 + shipmentsOrderInfo.setCreateById(SecurityUtil.getCurrentUser().getId());
  355 + shipmentsOrderInfo.setUpdateById(SecurityUtil.getCurrentUser().getId());
249 356
250   - create(createVo);
  357 + shipmentsOrderInfoList.add(shipmentsOrderInfo);
251 358 // 更新明细数据
252   - shipmentsPlanDetailService.setShipmentsOrderId(planDetailIds, id);
253   - // 获取订货单数据
254   -
  359 + shipmentsPlanDetailService.setShipmentsOrderId(detailIds, id);
  360 + }
  361 + // 获取所有部门数据
  362 + for ( ShipmentsOrderInfo orderInfo : shipmentsOrderInfoList) {
  363 + String id = orderInfo.getId();
  364 + List<String> deptIds = deptIdMap.get(id);
  365 + if (CollectionUtils.isNotEmpty(deptIds)) {
  366 + String deptIdStr = String.join(",", deptIds);
  367 + orderInfo.setDeptId(deptIdStr);
  368 + }
255 369 }
  370 + // 批量新增发货单
  371 + batchAdd(shipmentsOrderInfoList);
256 372 }
257 373 }
... ...
... ... @@ -314,6 +314,18 @@ public class ShipmentsPlanDetailServiceImpl extends BaseMpServiceImpl<ShipmentsP
314 314 getBaseMapper().update(updateWrapper);
315 315 }
316 316
  317 + @Override
  318 + public List<ShipmentsPlanDetail> listByPlanId(String planId) {
  319 + if (StringUtils.isBlank(planId)) {
  320 + return Collections.emptyList();
  321 + }
  322 + LambdaQueryWrapper<ShipmentsPlanDetail> queryWrapper = Wrappers.lambdaQuery(ShipmentsPlanDetail.class);
  323 + queryWrapper.eq(ShipmentsPlanDetail::getPlanId, planId)
  324 + .eq(ShipmentsPlanDetail::getDelFlag, Boolean.FALSE);
  325 +
  326 + return getBaseMapper().selectList(queryWrapper);
  327 + }
  328 +
317 329
318 330 /**
319 331 * 封装发货计划明细数据
... ...
... ... @@ -22,4 +22,11 @@ public interface ShipmentsOrderInfoMapper extends BaseMapper<ShipmentsOrderInfo>
22 22 * @return List<ShipmentsOrderInfo>
23 23 */
24 24 List<ShipmentsOrderInfo> query(@Param("vo") QueryShipmentsOrderInfoVo vo);
  25 +
  26 + /**
  27 + * 批量新增
  28 + *
  29 + * @param orderInfos 数据集合
  30 + */
  31 + void batchAdd(List<ShipmentsOrderInfo> orderInfos);
25 32 }
... ...
... ... @@ -114,4 +114,12 @@ public interface PurchaseOrderInfoService extends BaseMpService<PurchaseOrderInf
114 114 * @param orderInfo 订货单数据
115 115 */
116 116 void update(PurchaseOrderInfo orderInfo);
  117 +
  118 + /**
  119 + * 根据ID批量查询
  120 + *
  121 + * @param ids 主键ID集合
  122 + * @return List<PurchaseOrderInfo>
  123 + */
  124 + List<PurchaseOrderInfo> queryByIds(List<String> ids);
117 125 }
... ...
... ... @@ -65,4 +65,11 @@ public interface ShipmentsOrderInfoService extends BaseMpService<ShipmentsOrderI
65 65 * @param vo 生成条件
66 66 */
67 67 void generate(GenerateShipmentsOrderVo vo);
  68 +
  69 + /**
  70 + * 批量新增
  71 + *
  72 + * @param orderInfos 数据集合
  73 + */
  74 + void batchAdd(List<ShipmentsOrderInfo> orderInfos);
68 75 }
... ...
... ... @@ -96,4 +96,12 @@ public interface ShipmentsPlanDetailService extends BaseMpService<ShipmentsPlanD
96 96 * @param shipmentOrderId 发货单ID
97 97 */
98 98 void setShipmentsOrderId(List<String> ids, String shipmentOrderId);
  99 +
  100 + /**
  101 + * 根据计划ID查询
  102 + *
  103 + * @param planId 计划ID
  104 + * @return List<ShipmentsPlanDetail>
  105 + */
  106 + List<ShipmentsPlanDetail> listByPlanId(String planId);
99 107 }
... ...
1 1 package com.lframework.xingyun.sc.utils;
2 2
3 3 import lombok.extern.slf4j.Slf4j;
  4 +import org.apache.commons.collections4.CollectionUtils;
4 5
5 6 import java.io.*;
6 7 import java.math.BigDecimal;
7 8 import java.math.RoundingMode;
  9 +import java.util.ArrayList;
  10 +import java.util.Collections;
8 11 import java.util.List;
9 12
10 13 @Slf4j
... ... @@ -49,4 +52,29 @@ public class CommonUtil {
49 52 BigDecimal target = quantity.setScale(scale, RoundingMode.HALF_UP);
50 53 return sum.compareTo(target) == 0;
51 54 }
  55 +
  56 +
  57 + /**
  58 + * 将集合分成多个批次
  59 + *
  60 + * @param list 数据集合
  61 + * @param batchSize 一个批次的容量
  62 + * @return List<List<T>>
  63 + */
  64 + public static <T> List<List<T>> partition(List<T> list, int batchSize) {
  65 + if (CollectionUtils.isEmpty(list) || batchSize <= 0) {
  66 + return new ArrayList<>();
  67 + }
  68 + // 如果列表大小小于等于批次大小,直接返回包含原列表的单一批次
  69 + if (list.size() <= batchSize) {
  70 + return Collections.singletonList(list);
  71 + }
  72 + List<List<T>> batches = new ArrayList<>();
  73 + for (int i = 0; i < list.size(); i += batchSize) {
  74 + int end = Math.min(list.size(), i + batchSize);
  75 + batches.add(new ArrayList<>(list.subList(i, end)));
  76 + }
  77 + return batches;
  78 + }
  79 +
52 80 }
... ...
... ... @@ -61,4 +61,36 @@
61 61 </if>
62 62 </where>
63 63 </select>
  64 +
  65 + <insert id="batchAdd">
  66 + INSERT INTO shipments_order_info (
  67 + id,
  68 + plan_id,
  69 + customer_id,
  70 + workshop_id,
  71 + shipments_date,
  72 + dept_id,
  73 + delivery_type,
  74 + destination,
  75 + payment_type,
  76 + status,
  77 + create_by_id,
  78 + update_by_id
  79 + ) VALUES
  80 + <foreach collection="list" item="item" separator=",">
  81 + (
  82 + #{item.id},
  83 + #{item.planId},
  84 + #{item.customerId},
  85 + #{item.workshopId},
  86 + #{item.shipmentsDate},
  87 + #{item.deptId},
  88 + #{item.deliveryType},
  89 + #{item.destination},
  90 + #{item.status},
  91 + #{item.createById},
  92 + #{item.updateById}
  93 + )
  94 + </foreach>
  95 + </insert>
64 96 </mapper>
... ...