ShipmentContainerHeaderServiceImpl.java 19.3 KB
package com.huaheng.pc.shipment.shipmentContainerHeader.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huaheng.common.exception.service.ServiceException;
import com.huaheng.common.utils.security.ShiroUtils;
import com.huaheng.framework.web.domain.AjaxResult;
import com.huaheng.pc.general.location.domain.Location;
import com.huaheng.pc.general.location.service.LocationService;
import com.huaheng.pc.general.material.domain.Material;
import com.huaheng.pc.general.material.service.MaterialService;
import com.huaheng.pc.inventory.inventoryDetail.domain.InventoryDetail;
import com.huaheng.pc.inventory.inventoryDetail.service.InventoryDetailService;
import com.huaheng.pc.shipment.shipmentContainerDetail.domain.ShipmentContainerDetail;
import com.huaheng.pc.shipment.shipmentContainerDetail.service.ShipmentContainerDetailService;
import com.huaheng.pc.shipment.shipmentContainerHeader.domain.ShipmentCombinationModel;
import com.huaheng.pc.shipment.shipmentDetail.domain.ShipmentDetail;
import com.huaheng.pc.shipment.shipmentDetail.service.ShipmentDetailService;
import com.huaheng.pc.shipment.shipmentHeader.service.ShipmentHeaderService;
import com.huaheng.pc.shipment.shippingCombination.domain.ShippingSearch;
import com.huaheng.pc.shipment.shippingCombination.service.ShippingCombinationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaheng.pc.shipment.shipmentContainerHeader.domain.ShipmentContainerHeader;
import com.huaheng.pc.shipment.shipmentContainerHeader.mapper.ShipmentContainerHeaderMapper;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ShipmentContainerHeaderServiceImpl extends ServiceImpl<ShipmentContainerHeaderMapper, ShipmentContainerHeader> implements ShipmentContainerHeaderService{

    @Autowired
    private ShipmentDetailService shipmentDetailService;
    @Autowired
    private InventoryDetailService inventoryDetailService;
    @Autowired
    private LocationService locationService;
    @Autowired
    private ShipmentHeaderService shipmentHeaderService;
    @Resource
    private ShipmentContainerHeaderMapper shipmentContainerHeaderMapper;
    @Autowired
    private ShipmentContainerDetailService shipmentContainerDetailService;
    @Autowired
    private MaterialService materialService;
    @Autowired
    private ShippingCombinationService shippingCombinationService;


    @Override
    public Map<String, Integer> getShipmentContainerMaxAndMinStatusByShipmentID(int shipmentId) {
        return shipmentContainerHeaderMapper.getShipmentContainerMaxAndMinStatusByShipmentID(shipmentId);
    }



    /**
     * 出库组盘单条保存
     * @param shipmentCombinationModel
     * @return
     */
    @Transactional
    @Override
    public ShipmentContainerHeader combination(ShipmentCombinationModel shipmentCombinationModel) {

        //校验
        if(shipmentCombinationModel.getShipQty().compareTo(new BigDecimal("0")) <= 0){
            throw new ServiceException("出库数量必须大于0");
        }
        ShipmentDetail shipmentDetail = shipmentDetailService.getById(shipmentCombinationModel.getShipmentDetailId());
        if(shipmentDetail==null){
            throw new ServiceException("出库明细未找到");
        }
        InventoryDetail inventoryDetail = inventoryDetailService.getById((shipmentCombinationModel.getInventoryDetailId()));
        if(inventoryDetail==null){
            throw new ServiceException("库存未找到");
        }
        //校验数量是否超出
        if((shipmentDetail.getShipQty().subtract(shipmentDetail.getRequestQty())).compareTo(shipmentCombinationModel.getShipQty())<0){
            throw new ServiceException("录入数量超出明细待出数量");
        }
        //校验库存可用数量
        if(inventoryDetail.getQty().subtract(inventoryDetail.getTaskQty()).subtract(inventoryDetail.getLockedQty()).compareTo(shipmentCombinationModel.getShipQty())<0){
            throw new ServiceException("录入数量超出可出数量");
        }
        if(!shipmentDetail.getMaterialCode().equals(inventoryDetail.getMaterialCode())){
            throw new ServiceException("配盘物料不一致");
        }
        //库位
        LambdaQueryWrapper<Location> lambdaQueryWrapper= Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(Location::getWarehouseCode,inventoryDetail.getWarehouseCode())
                .eq(Location::getCode,inventoryDetail.getLocationCode());
        Location location = locationService.getOne(lambdaQueryWrapper);
        if (location == null)
            throw new ServiceException("库位 "+ inventoryDetail.getLocationCode() +" 不存在");
        if (location.getStatus().equals("lock"))    {
            //如果库位状态是锁定的话,就查找出库组盘表,如果存在未下发
            LambdaQueryWrapper<ShipmentContainerHeader> lam=Wrappers.lambdaQuery();
            lam.eq(ShipmentContainerHeader::getWarehouseCode,ShiroUtils.getWarehouseCode())
                    .eq(ShipmentContainerHeader::getContainerCode,location.getContainerCode())
                    .eq(ShipmentContainerHeader::getTaskCreated,0);
            ShipmentContainerHeader shipmentContainerHeader = this.getOne(lam);
            if (shipmentContainerHeader == null)    {
                throw new ServiceException("库位已经锁定不能使用");
            }
        }

        //更新库存分配数
        inventoryDetail.setTaskQty(inventoryDetail.getTaskQty().add(shipmentCombinationModel.getShipQty()));
        inventoryDetailService.saveOrUpdate(inventoryDetail);
        //获取库位,然后锁定
        location.setStatus("lock");
        locationService.saveOrUpdate(location);
        //更新单据明细的已出库数量
        shipmentDetail.setRequestQty(shipmentDetail.getRequestQty().add(shipmentCombinationModel.getShipQty()));
        int i = shipmentDetail.getShipQty().compareTo(shipmentDetail.getRequestQty());
        if(i > 0){
            shipmentDetail.setStatus(200);
        }else if(i == 0){
            shipmentDetail.setStatus(300);
        }else if(i < 0){
            throw new ServiceException("出库数量不能大于单据数量!");
        }
        shipmentDetailService.saveOrUpdate(shipmentDetail);

        //自动判定出库任务状态,根据库存数量减去预定库存相等就是整盘出--预计任务状态
        BigDecimal inventoryQty = inventoryDetail.getQty().subtract(inventoryDetail.getTaskQty());
        if(inventoryQty.compareTo(new BigDecimal(0)) <= 0) {
            shipmentCombinationModel.setTaskType(300);
        } else {
            shipmentCombinationModel.setTaskType(400);
        }

        //增加出库组盘头
        ShipmentContainerHeader shipmentContainerHeader = ShipmentContainerHeaderAdd(location, shipmentDetail, shipmentCombinationModel);
        //增加出库组盘明细
        ShipmentContainerDetail shipmentContainerDetail = ShipmentContainerDetailAdd(shipmentDetail, shipmentContainerHeader, shipmentCombinationModel);
        //更新单据状态
        shipmentHeaderService.updateShipmentStatus(shipmentDetail.getShipmentId());

        return  shipmentContainerHeader;
    }

    /**
     * 在组盘表中查找任务状态小于20的容器,如果状态为0就合并出库明细,状态大于0就提示不能组盘。如果找不到就新增一条组盘表头
     * @param location
     * @param shipmentCombination
     * @return
     */
    private ShipmentContainerHeader ShipmentContainerHeaderAdd(Location location,
                                                               ShipmentDetail shipmentDetail,
                                                               ShipmentCombinationModel shipmentCombination) {
        LambdaQueryWrapper<ShipmentContainerHeader> lambdaQueryWrapper=Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(ShipmentContainerHeader::getContainerCode,location.getContainerCode())
                .eq(ShipmentContainerHeader::getWarehouseCode,ShiroUtils.getWarehouseCode())
                .eq(ShipmentContainerHeader::getTaskCreated,1)
                .eq(ShipmentContainerHeader::getStatus,10);
        ShipmentContainerHeader shipmentContainerHeader = this.getOne(lambdaQueryWrapper);
        if(shipmentContainerHeader != null)  {
            throw new ServiceException("容器"+location.getContainerCode()+"已经生成任务,不能再添加明细;操作中止;");
        }
        else {
            LambdaQueryWrapper<ShipmentContainerHeader> lam=Wrappers.lambdaQuery();
            lam.eq(ShipmentContainerHeader::getContainerCode,location.getContainerCode())
                    .eq(ShipmentContainerHeader::getWarehouseCode,ShiroUtils.getWarehouseCode())
                    .eq(ShipmentContainerHeader::getTaskCreated,0)
                    .eq(ShipmentContainerHeader::getStatus,0);
            shipmentContainerHeader = this.getOne(lam);
            if (shipmentContainerHeader == null) {
                shipmentContainerHeader = new ShipmentContainerHeader();
                shipmentContainerHeader.setContainerCode(location.getContainerCode());
                shipmentContainerHeader.setWarehouseCode(ShiroUtils.getWarehouseCode());
                //赋值u8仓库
                shipmentContainerHeader.setCompanyCode(shipmentDetail.getCompanyCode());
                shipmentContainerHeader.setStatus(0);
                shipmentContainerHeader.setCreatedBy(ShiroUtils.getLoginName());
                shipmentContainerHeader.setCreated(null);
//            Material material=new Material();
//            material.setCode(shipmentDetail.getMaterialCode());
//            shipmentContainerHeader.setZoneCode(materialService.selectFirstEntity(material).getZoneCode());
                this.save(shipmentContainerHeader);
            }
        }
        return shipmentContainerHeader;
    }

    /**
     * 查询 容器编码、库存Id、出库明细Id 一致的组盘明细,如果存在则增加组盘数量,如果不存在就新增一条组盘明细
     * @param shipmentDetail
     * @param shipmentContainerHeader
     * @param shipmentCombinationModel
     * @return
     */
    private ShipmentContainerDetail ShipmentContainerDetailAdd(ShipmentDetail shipmentDetail,
                                                               ShipmentContainerHeader shipmentContainerHeader,
                                                               ShipmentCombinationModel shipmentCombinationModel) {
        LambdaQueryWrapper<ShipmentContainerDetail> lambdaQueryWrapper=Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(ShipmentContainerDetail::getShippingContainerId,shipmentContainerHeader.getId())
                .eq(ShipmentContainerDetail::getShipmentDetailId,shipmentCombinationModel.getShipmentDetailId())
                .eq(ShipmentContainerDetail::getWarehouseCode,ShiroUtils.getWarehouseCode());
        ShipmentContainerDetail shipmentContainerDetail = shipmentContainerDetailService.getOne(lambdaQueryWrapper);
        if(shipmentContainerDetail != null)    {
            shipmentContainerDetail.setQty(shipmentContainerDetail.getQty().add(shipmentCombinationModel.getShipQty()));
            shipmentContainerDetailService.saveOrUpdate(shipmentContainerDetail);
        }
        else    {
            //构建明细

            LambdaQueryWrapper<Material> lam=Wrappers.lambdaQuery();
            lam.eq(Material::getCode,shipmentDetail.getMaterialCode())
                    .eq(Material::getWarehouseCode,ShiroUtils.getWarehouseCode());
            Material material = materialService.getOne(lam);
            if (material == null)
                throw new ServiceException("出库单(" + shipmentDetail.getShipmentCode() + ")的物料("+ shipmentDetail.getMaterialCode() +")不存在!");
            shipmentContainerDetail = new ShipmentContainerDetail();
            shipmentContainerDetail.setShippingContainerId(shipmentContainerHeader.getId());
            shipmentContainerDetail.setShipmentCode(shipmentDetail.getShipmentCode());
            shipmentContainerDetail.setShipmentId(shipmentDetail.getShipmentId());
            shipmentContainerDetail.setShipmentDetailId(shipmentCombinationModel.getShipmentDetailId());
            shipmentContainerDetail.setMaterialCode(material.getCode());
            shipmentContainerDetail.setMaterialName(material.getName());
            shipmentContainerDetail.setQty(shipmentCombinationModel.getShipQty());
            shipmentContainerDetail.setCreated(null);
            shipmentContainerDetail.setCreatedBy(ShiroUtils.getLoginName());
            shipmentContainerDetailService.save(shipmentContainerDetail);
        }
        return shipmentContainerDetail;
    }


    /**
     * 取消组盘的一组明细
     * @param detailIds
     * @return
     */
    @Override
    public AjaxResult cancelCombinationDetail(List<Integer> detailIds)  {
        List<ShipmentContainerDetail> shipmentContainerDetails = new ArrayList<>();
        for(int detailId:detailIds){
            ShipmentContainerDetail shipmentContainerDetail = shipmentContainerDetailService.getById(detailId);
            shipmentContainerDetails.add(shipmentContainerDetail);
        }
        return cancelCombinationDetailInner(shipmentContainerDetails);
    }

    /**
     * 取消组盘的一组明细
     * @param shipmentContainerDetails
     * @return
     */
    @Override
    @Transactional
    public AjaxResult cancelCombinationDetailInner(List<ShipmentContainerDetail> shipmentContainerDetails)  {
        for(ShipmentContainerDetail shipmentContainerDetail:shipmentContainerDetails){
            //获取头
            ShipmentContainerHeader shipmentContainerHeader = this.getById(shipmentContainerDetail.getShippingContainerId());
            if(shipmentContainerHeader.getStatus()>9){
                return AjaxResult.error("容器"+shipmentContainerHeader.getContainerCode()+"非新建状态,不允许取消明细");
            }
            //恢复占用库存
            InventoryDetail inventoryDetail = inventoryDetailService.getById(shipmentContainerDetail.getInventoryId());
            inventoryDetail.setTaskQty(inventoryDetail.getTaskQty().subtract(shipmentContainerDetail.getQty()));
            inventoryDetailService.saveOrUpdate(inventoryDetail);
            //恢复单据发货数量
            ShipmentDetail shipmentDetail = shipmentDetailService.getById(shipmentContainerDetail.getShipmentDetailId());
            shipmentDetail.setRequestQty(shipmentDetail.getRequestQty().subtract(shipmentContainerDetail.getQty()));
            if(shipmentDetail.getRequestQty().compareTo(BigDecimal.ZERO) != 0 ){
                shipmentDetail.setStatus(200);//明细状态恢复,如果删除后还有以出数量就是波次
            }else{
                shipmentDetail.setStatus(0 );//明细状态
            }
            shipmentDetailService.saveOrUpdate(shipmentDetail);
            //删除这个配盘明细
            shipmentContainerDetailService.removeById(shipmentContainerDetail.getId());

            //查询头表下还有没有明细,如果没有,则删了这个头表
            ShipmentContainerDetail condition = new ShipmentContainerDetail();
            condition.setShippingContainerId(shipmentContainerDetail.getShippingContainerId());
            List<Map<String, Object>> list= shipmentContainerDetailService.selectListMapByEqual("id", condition);
            if(list==null||list.size() == 0){
                this.removeById(shipmentContainerHeader.getId());
                locationService.updateStatus(shipmentContainerHeader.getLocationCode(),"empty");
            }
            //更新单据状态
            shipmentHeaderService.updateShipmentStatus(shipmentDetail.getShipmentId());
        }
        return AjaxResult.success("");
    }


    /**
     *  出库自动组盘
     * @param shipmentCode
     * @return
     */
    @Override
    @Transactional
    public AjaxResult autoCombination(String shipmentCode) {
        int num=0;
        AjaxResult ajaxResult=new AjaxResult();

        LambdaQueryWrapper<ShipmentDetail> lambdaQueryWrapper=Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(ShipmentDetail::getShipmentCode,shipmentCode)
                .eq(ShipmentDetail::getWarehouseCode,ShiroUtils.getWarehouseCode());
        List<ShipmentDetail> shipmentDetailList = shipmentDetailService.list(lambdaQueryWrapper);
        if(shipmentDetailList.size()<1 || shipmentDetailList==null){
            return AjaxResult.error("找不到子单链");
        }
        for (ShipmentDetail item : shipmentDetailList) {
            //获取需要出库数量
            BigDecimal shipmentQty = item.getShipQty().subtract(item.getRequestQty());
            //判断是否还有需要出库的物料,如果没有就跳过该物料
            if (shipmentQty.compareTo(BigDecimal.ZERO) <= 0) {
                continue;
            }
            // 根据 仓库编码、货主编码、存货编码,物料状态,项目号来查找可以出库的物料
            ShippingSearch search = new ShippingSearch();
            search.setWarehouseCode(ShiroUtils.getWarehouseCode());
            search.setCompanyCode(item.getCompanyCode());
            search.setMaterialCode(item.getMaterialCode());
            search.setInventorySts(item.getInventorySts()); //物料状态

            List<InventoryDetail> inventoryList = shippingCombinationService.getInventorys(search);
            if (inventoryList.size() < 1) {
                num = num + 1;
            } else {
                for (InventoryDetail inventory : inventoryList) {
                    //判断是否组盘完毕,完毕就退出内循环
                    if (shipmentQty.compareTo(BigDecimal.ZERO) <= 0) {
                        break;
                    }

                    BigDecimal inventoryQty = inventory.getQty().subtract(inventory.getTaskQty());
                    ShipmentCombinationModel shipmentCombination = new ShipmentCombinationModel();
                    shipmentCombination.setInventoryDetailId(inventory.getId());
                    shipmentCombination.setShipmentDetailId(item.getId());
                    shipmentCombination.setType((short) 300);
                    List<Integer> list=new ArrayList<>();
                    //如果库存数 >= 待出库数,组盘数就是待出库数并且结束组盘,否则组盘数就是库存数
                    if (inventoryQty.compareTo(shipmentQty) > -1) {
                        shipmentCombination.setShipQty(shipmentQty);
                        ShipmentContainerHeader shipmentContainerHeader=this.combination(shipmentCombination);
                    } else {
                        shipmentCombination.setShipQty(inventoryQty);
                        ShipmentContainerHeader shipmentContainerHeader=this.combination(shipmentCombination);
                        list.add(shipmentContainerHeader.getId());
                    }
                    shipmentQty = shipmentQty.subtract(shipmentCombination.getShipQty());
                }
            }
        }
        if(num==shipmentDetailList.size()){
            throw new ServiceException("单据物料在此库区没有库存,无法出库");
        }
        return AjaxResult.success("");
    }

}