preface
Here I will pay more attention to the writing of business logic and the process of related configuration. If you have any questions, you can comment or contact me to communicate with each other. Original video address Grain Mall (Lei Fengyang Edition) . My git warehouse address Grain mall in Draknessssw
Warehouse query
First, configure the nacos configuration center and routing rules
Implementation class
Query criteria: fuzzy matching id, name, address, area code
@Override public PageUtils queryPage(Map<String, Object> params) { QueryWrapper<WareInfoEntity> queryWrapper = new QueryWrapper<>(); String key = (String) params.get("key"); if (!StringUtils.isEmpty(key)) { queryWrapper.eq("id",key) .or().like("name",key) .or().like("address",key) .or().like("areacode",key); } IPage<WareInfoEntity> page = this.page( new Query<WareInfoEntity>().getPage(params), queryWrapper );
Warehouse information query
/** * list */ @RequestMapping("/list") public R list(@RequestParam Map<String, Object> params){ PageUtils page = wareSkuService.queryPage(params); return R.ok().put("page", page); }
Implementation class
Query the warehouse information according to the warehouse information id and the warehouse id.
@Override public PageUtils queryPage(Map<String, Object> params) { QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>(); String skuId = (String) params.get("skuId"); if (!StringUtils.isEmpty(skuId) && !"0".equalsIgnoreCase(skuId)) { queryWrapper.eq("sku_id",skuId); } String wareId = (String) params.get("wareId"); if (!StringUtils.isEmpty(wareId) && !"0".equalsIgnoreCase(wareId)) { queryWrapper.eq("ware_id",wareId); } IPage<WareSkuEntity> page = this.page( new Query<WareSkuEntity>().getPage(params), queryWrapper ); return new PageUtils(page); }
Query purchase order
/** * list */ @RequestMapping("/list") public R list(@RequestParam Map<String, Object> params){ PageUtils page = purchaseDetailService.queryPage(params); return R.ok().put("page", page); }
Implementation class
Fuzzy matching between purchase order id and warehouse information id. It is also attached to query the purchase order status and warehouse id.
@Override public PageUtils queryPage(Map<String, Object> params) { QueryWrapper<PurchaseDetailEntity> queryWrapper = new QueryWrapper<PurchaseDetailEntity>(); String key = (String) params.get("key"); if (!StringUtils.isEmpty(key)) { queryWrapper.and(wrapper -> { wrapper.eq("purchase_id",key).or().eq("sku_id",key); }); } String status = (String) params.get("status"); if (!StringUtils.isEmpty(status) && !"0".equalsIgnoreCase(status)) { queryWrapper.eq("status",status); } String wareId = (String) params.get("wareId"); if (!StringUtils.isEmpty(wareId) && !"0".equalsIgnoreCase(wareId)) { queryWrapper.eq("ware_id",wareId); } IPage<PurchaseDetailEntity> page = this.page( new Query<PurchaseDetailEntity>().getPage(params), queryWrapper ); return new PageUtils(page); }
Consolidated purchase order
Query unconsolidated purchase orders
///ware/purchase/unreceive/list @GetMapping(value = "/unreceive/list") public R unreceiveList(@RequestParam Map<String, Object> params){ PageUtils page = purchaseService.queryPageUnreceive(params); return R.ok().put("page", page); }
Implementation class
Match the two statuses of the purchase order
/** * Query unclaimed purchase orders * @param params * @return */ @Override public PageUtils queryPageUnreceive(Map<String, Object> params) { QueryWrapper<PurchaseEntity> queryWrapper = new QueryWrapper<PurchaseEntity>() .eq("status",0).or().eq("status",1); IPage<PurchaseEntity> page = this.page( new Query<PurchaseEntity>().getPage(params), queryWrapper ); return new PageUtils(page); }
Consolidated purchase order
New VO
package com.xxxx.gulimall.ware.vo; import lombok.Data; import java.util.List; @Data public class MergeVo { private Long purchaseId; private List<Long> items; }
/** * Consolidated whole document * @param mergeVo * @return */ ///ware/purchase/merge @PostMapping(value = "/merge") public R merge(@RequestBody MergeVo mergeVo) { purchaseService.mergePurchase(mergeVo); return R.ok(); }
First, get the Po id in the Vo returned by the page. If not, create a new PO. Set its purchase status to new, and save after setting the creation time and update time. Then get the id of the new PO
Long purchaseId = mergeVo.getPurchaseId(); //If no purchase order is selected, a new order will be automatically created for consolidation. if (purchaseId == null) { PurchaseEntity purchaseEntity = new PurchaseEntity(); //Set the default status of purchase orders purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode()); purchaseEntity.setCreateTime(new Date()); purchaseEntity.setUpdateTime(new Date()); this.save(purchaseEntity); //Get the id of the new purchase order purchaseId = purchaseEntity.getId(); }
Public enumeration class about state
package com.xxxx.common.constant; public class WareConstant { public enum PurchaseStatusEnum { CREATED(0,"newly build"), ASSIGNED(1,"Allocated"), RECEIVE(2,"Received"), FINISH(3,"Completed"), HASERROR(4,"Abnormal"), ; private int code; private String msg; public int getCode() { return code; } public String getMsg() { return msg; } PurchaseStatusEnum(int code, String msg) { this.code = code; this.msg = msg; } } public enum PurchaseDetailStatusEnum { CREATED(0,"newly build"), ASSIGNED(1,"Allocated"), BUYING(2,"Purchasing"), FINISH(3,"Completed"), HASERROR(4,"Purchase failed"), ; private int code; private String msg; public int getCode() { return code; } public String getMsg() { return msg; } PurchaseDetailStatusEnum(int code, String msg) { this.code = code; this.msg = msg; } } }
Obtain the purchase item id of Vo when the status of Po details is not new or allocated. Then you can directly throw a user-defined exception and cannot allocate these purchase orders
List<Long> items = mergeVo.getItems(); //TODO: confirm that the PO status is 0,1 before consolidation Collection<PurchaseDetailEntity> purchaseDetailEntities = purchaseDetailService.listByIds(items); purchaseDetailEntities.forEach((item) -> { if (!item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.CREATED.getCode()) && !item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode())) { throw new IllegalArgumentException("Purchasing, unable to allocate"); } });
Access the id of the purchase order, create a new purchase item, set its id and purchase order id, and set its status to allocated. Then modify purchase items in batch.
Long finalPurchaseId = purchaseId; List<PurchaseDetailEntity> collect = items.stream().map(i -> { PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity(); purchaseDetailEntity.setId(i); purchaseDetailEntity.setPurchaseId(finalPurchaseId); purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode()); return purchaseDetailEntity; }).collect(Collectors.toList()); //Batch modification purchaseDetailService.updateBatchById(collect);
Then, modify the update time of the purchase order according to the purchase order id
PurchaseEntity purchaseEntity = new PurchaseEntity(); purchaseEntity.setId(purchaseId); purchaseEntity.setUpdateTime(new Date()); this.updateById(purchaseEntity);
The final effect is as follows:
@Autowired private PurchaseDetailService purchaseDetailService;
/** * Consolidated purchase demand * @param mergeVo */ @Transactional @Override public void mergePurchase(MergeVo mergeVo) { Long purchaseId = mergeVo.getPurchaseId(); //If no purchase order is selected, a new order will be automatically created for consolidation. if (purchaseId == null) { PurchaseEntity purchaseEntity = new PurchaseEntity(); //Set the default status of purchase orders purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode()); purchaseEntity.setCreateTime(new Date()); purchaseEntity.setUpdateTime(new Date()); this.save(purchaseEntity); //Get the id of the new purchase order purchaseId = purchaseEntity.getId(); } List<Long> items = mergeVo.getItems(); //TODO: confirm that the PO status is 0,1 before consolidation Collection<PurchaseDetailEntity> purchaseDetailEntities = purchaseDetailService.listByIds(items); purchaseDetailEntities.forEach((item) -> { if (!item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.CREATED.getCode()) && !item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode())) { throw new IllegalArgumentException("Purchasing, unable to allocate"); } }); Long finalPurchaseId = purchaseId; List<PurchaseDetailEntity> collect = items.stream().map(i -> { PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity(); purchaseDetailEntity.setId(i); purchaseDetailEntity.setPurchaseId(finalPurchaseId); purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode()); return purchaseDetailEntity; }).collect(Collectors.toList()); //Batch modification purchaseDetailService.updateBatchById(collect); PurchaseEntity purchaseEntity = new PurchaseEntity(); purchaseEntity.setId(purchaseId); purchaseEntity.setUpdateTime(new Date()); this.updateById(purchaseEntity); }
Receive purchase order
/** * Receive purchase order * @param ids * @return */ @PostMapping(value = "/received") public R received(@RequestBody List<Long> ids) { purchaseService.received(ids); return R.ok(); }
Implementation class
First, obtain the purchase order information according to the purchase order id to be collected. Confirm that the purchase orders are in new or allocated status, and then filter out these purchase orders, and change the purchase order status to received
//1. Confirm whether the current purchase order is new or allocated List<PurchaseEntity> collect = ids.stream().map(id -> { PurchaseEntity byId = this.getById(id); return byId; }).filter(item -> { if (item.getStatus() == WareConstant.PurchaseStatusEnum.CREATED.getCode() || item.getStatus() == WareConstant.PurchaseStatusEnum.ASSIGNED.getCode()) { return true; } return false; }).map(item -> { //Purchase order with changed status item.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode()); item.setUpdateTime(new Date()); return item; }).collect(Collectors.toList());
Batch update PO status
//2. Change the status of the purchase order this.updateBatchById(collect);
Find out the id of the received purchase order, and then set the purchase order id of the purchase item and the purchasing status according to these purchase order IDs. Then save these purchase items in batch.
//3. Change the status of the purchase item collect.forEach((item) -> { List<PurchaseDetailEntity> list = purchaseDetailService.listDetailByPurchaseId(item.getId()); List<PurchaseDetailEntity> detailEntities = list.stream().map(entity -> { PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity(); purchaseDetailEntity.setId(entity.getId()); purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode()); return purchaseDetailEntity; }).collect(Collectors.toList()); purchaseDetailService.updateBatchById(detailEntities); });
Implementation method for querying received purchase orders
@Override public List<PurchaseDetailEntity> listDetailByPurchaseId(Long id) { List<PurchaseDetailEntity> purchaseId = this.list( new QueryWrapper<PurchaseDetailEntity>().eq("purchase_id", id)); return purchaseId; }
The final effect is as follows:
@Autowired private PurchaseDetailService purchaseDetailService;
/** * Consolidated purchase demand * @param mergeVo */ @Transactional @Override public void mergePurchase(MergeVo mergeVo) { Long purchaseId = mergeVo.getPurchaseId(); //If no purchase order is selected, a new order will be automatically created for consolidation. if (purchaseId == null) { PurchaseEntity purchaseEntity = new PurchaseEntity(); //Set the default status of purchase orders purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode()); purchaseEntity.setCreateTime(new Date()); purchaseEntity.setUpdateTime(new Date()); this.save(purchaseEntity); //Get the id of the new purchase order purchaseId = purchaseEntity.getId(); } List<Long> items = mergeVo.getItems(); //TODO: confirm that the PO status is 0,1 before consolidation Collection<PurchaseDetailEntity> purchaseDetailEntities = purchaseDetailService.listByIds(items); purchaseDetailEntities.forEach((item) -> { if (!item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.CREATED.getCode()) && !item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode())) { throw new IllegalArgumentException("Purchasing, unable to allocate"); } }); Long finalPurchaseId = purchaseId; List<PurchaseDetailEntity> collect = items.stream().map(i -> { PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity(); purchaseDetailEntity.setId(i); purchaseDetailEntity.setPurchaseId(finalPurchaseId); purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode()); return purchaseDetailEntity; }).collect(Collectors.toList()); //Batch modification purchaseDetailService.updateBatchById(collect); PurchaseEntity purchaseEntity = new PurchaseEntity(); purchaseEntity.setId(purchaseId); purchaseEntity.setUpdateTime(new Date()); this.updateById(purchaseEntity); }
Complete purchase order
Purchase completed VO, which encapsulates the purchase item Vo
package com.xxxx.gulimall.ware.vo; import lombok.Data; import javax.validation.constraints.NotNull; import java.util.List; @Data public class PurchaseDoneVo { @NotNull(message = "id Cannot be empty") private Long id; private List<PurchaseItemDoneVo> items; }
Purchase item Vo
package com.xxxx.gulimall.ware.vo; import lombok.Data; @Data public class PurchaseItemDoneVo { private Long itemId; private Integer status; private String reason; }
/** * Complete purchase order * @param doneVo * @return */ @PostMapping(value = "/done") public R finish(@RequestBody PurchaseDoneVo doneVo) { purchaseService.done(doneVo); return R.ok(); }
Implementation class
First, get the purchase order id to complete the purchase
Long id = doneVo.getId();
Traverse the completed purchase items returned from the page. If the purchase item status in the Vo returned from the page is purchase failed, set the purchase item status to failed, and set the purchase item status flag data to false.
Otherwise, all other purchase item statuses can be set to completed when setting is completed. Then query the details of the currently successfully completed purchase items and call the remote service for warehousing.
After setting the status of the purchase item, set the id. Add the purchase item data to the purchase item list. At this time, you can batch update the purchase item data according to the purchase item list data
for (PurchaseItemDoneVo item : items) { PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity(); if (item.getStatus() == WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode()) { flag = false; purchaseDetailEntity.setStatus(item.getStatus()); } else { purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISH.getCode()); //3. Stock in the successfully purchased goods //Find out the details of the current purchase item //PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId()); PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId()); wareSkuService.addStock(entity.getSkuId(),entity.getWareId(),entity.getSkuNum()); } purchaseDetailEntity.setId(item.getItemId()); updates.add(purchaseDetailEntity); } //Batch update purchaseDetailService.updateBatchById(updates);
Then, the purchase order information is updated according to the purchase order id and the boolean value of the purchase success or failure identification.
//2. Change PO status PurchaseEntity purchaseEntity = new PurchaseEntity(); purchaseEntity.setId(id); purchaseEntity.setStatus(flag?WareConstant.PurchaseStatusEnum.FINISH.getCode():WareConstant.PurchaseStatusEnum.HASERROR.getCode()); purchaseEntity.setUpdateTime(new Date()); this.updateById(purchaseEntity);
The final effect is as follows:
@Autowired private PurchaseDetailService purchaseDetailService; @Autowired private WareSkuService wareSkuService;
@Transactional @Override public void done(PurchaseDoneVo doneVo) { Long id = doneVo.getId(); //1. Change the status of the purchase item Boolean flag = true; List<PurchaseItemDoneVo> items = doneVo.getItems(); List<PurchaseDetailEntity> updates = new ArrayList<>(); for (PurchaseItemDoneVo item : items) { PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity(); if (item.getStatus() == WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode()) { flag = false; purchaseDetailEntity.setStatus(item.getStatus()); } else { purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISH.getCode()); //3. Stock in the successfully purchased goods //Find out the details of the current purchase item //PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId()); PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId()); wareSkuService.addStock(entity.getSkuId(),entity.getWareId(),entity.getSkuNum()); } purchaseDetailEntity.setId(item.getItemId()); updates.add(purchaseDetailEntity); } //Batch update purchaseDetailService.updateBatchById(updates); //2. Change PO status PurchaseEntity purchaseEntity = new PurchaseEntity(); purchaseEntity.setId(id); purchaseEntity.setStatus(flag?WareConstant.PurchaseStatusEnum.FINISH.getCode():WareConstant.PurchaseStatusEnum.HASERROR.getCode()); purchaseEntity.setUpdateTime(new Date()); this.updateById(purchaseEntity); }
The remote service method for adding inventory is as follows:
Determine whether this inventory record exists in the inventory table
List<WareSkuEntity> wareSkuEntities = wareSkuDao.selectList( new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));
If there is no inventory record, add it; if there is, modify the inventory information
When adding inventory, the name needs to query the inventory information remotely
Remote feign method
package com.xxxx.gulimall.ware.feign; import com.xxxx.common.utils.R; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @FeignClient(value = "gulimall-product") public interface ProductFeignService { /** * /product/skuinfo/info/{skuId} * * * 1),Let all requests pass through the gateway; * 1,@FeignClient("gulimall-gateway"): Send a request to the machine where the gulimall gateway is located * 2,/api/product/skuinfo/info/{skuId} * 2),Directly let the background specify service processing * 1,@FeignClient("gulimall-product") * 2,/product/skuinfo/info/{skuId} * * @return */ @RequestMapping("/product/skuinfo/info/{skuId}") public R info(@PathVariable("skuId") Long skuId); }
The final effect is:
@Autowired private WareSkuDao wareSkuDao;
@Transactional @Override public void addStock(Long skuId, Long wareId, Integer skuNum) { //1. Interpretation: if there is no inventory record, add List<WareSkuEntity> wareSkuEntities = wareSkuDao.selectList( new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId)); if (wareSkuEntities == null || wareSkuEntities.size() == 0) { WareSkuEntity wareSkuEntity = new WareSkuEntity(); wareSkuEntity.setSkuId(skuId); wareSkuEntity.setStock(skuNum); wareSkuEntity.setWareId(wareId); wareSkuEntity.setStockLocked(0); //TODO queries the name of sku remotely. If it fails, the whole transaction does not need to be rolled back //1. Own catch exception try{ R info = productFeignService.info(skuId); Map<String,Object> data = (Map<String, Object>) info.get("skuInfo"); if (info.getCode() == 0) { wareSkuEntity.setSkuName((String) data.get("skuName")); } } catch (Exception e) { } //Add inventory information wareSkuDao.insert(wareSkuEntity); } else { //Modify inventory information wareSkuDao.addStock(skuId,wareId,skuNum); } }
sql for modifying inventory information
<update id="addStock"> UPDATE wms_ware_sku SET stock = stock + #{skuNum} WHERE sku_id = #{skuId} AND ware_id = #{wareId} </update>