2022 grain mall learning notes warehouse management function

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>

Tags: Java Distribution

Posted by Chiaki on Tue, 23 Aug 2022 11:00:23 +0530