ReceivingService.java 16 KB
package com.huaheng.pc.receipt.receiving.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huaheng.api.wcs.service.warecellAllocation.LocationAllocationService;
import com.huaheng.common.constant.QuantityConstant;
import com.huaheng.common.exception.service.ServiceException;
import com.huaheng.common.support.Convert;
import com.huaheng.common.utils.StringUtils;
import com.huaheng.common.utils.security.ShiroUtils;
import com.huaheng.framework.web.domain.AjaxResult;
import com.huaheng.framework.web.service.ConfigService;
import com.huaheng.pc.config.FilterConfigDetail.domain.FilterConfigDetail;
import com.huaheng.pc.config.FilterConfigDetail.service.FilterConfigDetailService;
import com.huaheng.pc.config.configValue.domain.ConfigValue;
import com.huaheng.pc.config.configValue.service.ConfigValueService;
import com.huaheng.pc.config.container.domain.Container;
import com.huaheng.pc.config.container.service.ContainerService;
import com.huaheng.pc.config.containerType.domain.ContainerType;
import com.huaheng.pc.config.containerType.service.ContainerTypeService;
import com.huaheng.pc.config.location.domain.Location;
import com.huaheng.pc.config.location.service.LocationService;
import com.huaheng.pc.config.locationType.domain.LocationType;
import com.huaheng.pc.config.locationType.service.LocationTypeService;
import com.huaheng.pc.config.material.domain.Material;
import com.huaheng.pc.config.material.service.MaterialService;
import com.huaheng.pc.config.materialType.domain.MaterialType;
import com.huaheng.pc.config.materialType.service.MaterialTypeService;
import com.huaheng.pc.config.receiptPreference.domain.ReceiptPreference;
import com.huaheng.pc.config.receiptPreference.service.ReceiptPreferenceService;
import com.huaheng.pc.receipt.receiptContainerDetail.domain.ReceiptContainerDetail;
import com.huaheng.pc.receipt.receiptContainerDetail.service.ReceiptContainerDetailService;
import com.huaheng.pc.receipt.receiptContainerHeader.domain.ReceiptContainerHeader;
import com.huaheng.pc.receipt.receiptContainerHeader.service.ReceiptContainerHeaderService;
import com.huaheng.pc.receipt.receiptDetail.domain.ReceiptDetail;
import com.huaheng.pc.receipt.receiptHeader.domain.ReceiptHeader;
import com.huaheng.pc.task.taskHeader.service.TaskHeaderService;
import com.huaheng.pc.task.taskHeader.service.TransferTaskService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.huaheng.pc.receipt.receiptDetail.service.ReceiptDetailService;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author mahua
 * @ClassName ReceivingService
 * @projectName huaheng
 * @description: TODO
 * @date 2019/8/3123:09
 */
@Service
public class ReceivingService {

    @Resource
    private ReceiptDetailService receiptDetailService;
    @Resource
    private ReceiptContainerHeaderService receiptContainerHeaderService;
    @Resource
    private ReceiptContainerDetailService receiptContainerDetailService;
    @Resource
    private LocationService locationService;
    @Resource
    private MaterialService materialService;
    @Resource
    private MaterialTypeService materialTypeService;
    @Resource
    private ConfigValueService configValueService;
    @Resource
    private ReceiptPreferenceService preferenceService;
    @Resource
    private FilterConfigDetailService filterConfigDetailService;
    @Resource
    private ContainerService containerService;
    @Resource
    private ConfigService configService;
    @Resource
    private TaskHeaderService taskHeaderService;
    @Resource
    private LocationTypeService locationTypeService;
    @Resource
    private TransferTaskService transferTaskService;
    @Resource
    private ContainerTypeService containerTypeService;
    @Resource
    private LocationAllocationService locationAllocationService;


    /**
     * 获取当前单号详情
     * @param receiptCode 入库单号
     * @return 入库单详情
     */
    @Transactional
    public AjaxResult<List<ReceiptDetail>> scanReceiptCode(String receiptCode)  {
        //根据仓库编码和入库单号查询入库单详情
        LambdaQueryWrapper<ReceiptDetail> lambda = new LambdaQueryWrapper<>();
        lambda.eq(ReceiptDetail::getReceiptCode, receiptCode)
                .eq(ReceiptDetail::getWarehouseCode, ShiroUtils.getWarehouseCode());

        List<ReceiptDetail> detail = receiptDetailService.list(lambda);
        return AjaxResult.success(detail);
    }

    public String filter(List<Location> locationList, List<LocationType> locationTypeList, Container container){
        String containerType1 = container.getContainerType();
        LambdaQueryWrapper<ContainerType> containerTypeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        containerTypeLambdaQueryWrapper.eq(ContainerType::getCode, containerType1);
        containerTypeLambdaQueryWrapper.eq(ContainerType::getWarehouseCode, ShiroUtils.getWarehouseCode());
        ContainerType containerType = containerTypeService.getOne(containerTypeLambdaQueryWrapper);
        String locationType = containerType.getLocationType();
        String[] locationTypes = locationType.split(",");
//        List<String> codeList = locationTypeList.stream().map(t-> t.getCode()).collect(Collectors.toList());
        List<String> codeList = new ArrayList<>();
        for(String type : locationTypes) {
            codeList.add(type);
        }
        List<Location> newLocation = locationList.stream().filter(t-> codeList.contains(t.getLocationType())).collect(Collectors.toList());
        if (newLocation.isEmpty()){
            return null;
        } else{
            return newLocation.get(0).getCode();
        }
    }

    /**
     * 定位
     * @param receiptContainerDetail 入库明细
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean  position(ReceiptContainerDetail receiptContainerDetail, String area){
        ReceiptContainerHeader receiptContainerHeader = receiptContainerHeaderService.getById(receiptContainerDetail.getReceiptContainerId());
        if (!QuantityConstant.RECEIPT_CONTAINER_BUILD.equals(receiptContainerHeader.getStatus())){
            throw new ServiceException(receiptContainerHeader.getContainerCode()+"入库组盘已生成任务不能重新定位");
        }
        //如果入库组盘表中有目标库位说明已经指定
        if (StringUtils.isNotEmpty(receiptContainerHeader.getToLocation())){ return true; }
        /* 判断入盘容器是否在库位上*/
        Container container = containerService.getContainerByCode(receiptContainerHeader.getContainerCode());
        if (StringUtils.isNotEmpty(container.getLocationCode())) {
            receiptContainerHeader.setFromLocation(container.getLocationCode());
            receiptContainerHeader.setToLocation(container.getLocationCode());
            receiptContainerHeader.setTaskType(QuantityConstant.TASK_TYPE_SUPPLEMENTRECEIPT);
            if (!receiptContainerHeaderService.updateById(receiptContainerHeader)) {
                throw new ServiceException("更新定位失败");
            } else {
                return true;
            }
        }

        String value = configService.getKey(QuantityConstant.RULE_ALLOCATION);
        if (StringUtils.isEmpty(value)) {
            throw new ServiceException("未绑定定位规则");
        }
        int allocationRule = Integer.parseInt(value);
        Material material = materialService.findAllByCode(receiptContainerDetail.getMaterialCode());
        String materialAreaCode = material.getMaterialAreaCode();
        String locationCode = locationAllocationService.allocation(allocationRule, null, 0, area, ShiroUtils.getWarehouseCode(),container.getCode(), materialAreaCode);

        if (StringUtils.isNotEmpty(locationCode)){
            locationService.updateStatus(locationCode, QuantityConstant.STATUS_LOCATION_LOCK);
        } else {
            throw new ServiceException("定位失败,请检查定位规则是否正确");
        }
        LambdaQueryWrapper<Location> locationLambdaQueryWrapper = Wrappers.lambdaQuery();
        locationLambdaQueryWrapper.eq(Location::getCode, locationCode);
        locationLambdaQueryWrapper.eq(Location::getWarehouseCode, ShiroUtils.getWarehouseCode());
        Location location = locationService.getOne(locationLambdaQueryWrapper);
        int rowFlag = location.getRowFlag().intValue();
        Integer preTaskNo = 0;
        //如果是外侧库位,那么就要判断该库位对应的内侧库位是不是有托盘
        if(rowFlag == QuantityConstant.ROW_OUT) {
            Location insideLocation = locationService.getInsideNear(location);
            if(StringUtils.isNotEmpty(insideLocation.getContainerCode())) {
                Location destinationLocation = locationService.getEmptyLocation(insideLocation);
                AjaxResult ajaxResult = transferTaskService.createTransferTask(insideLocation.getCode(), destinationLocation.getCode());
                preTaskNo = (Integer) ajaxResult.getData();
                if(ajaxResult.hasErr()) {
                    throw new ServiceException("创建移库任务失败");
                }
                taskHeaderService.sendTaskToWcs(Convert.toIntArray(String.valueOf(preTaskNo)));
            }
        }


        //更新库位编码到组盘头表
        receiptContainerHeader.setToLocation(locationCode);
        receiptContainerHeader.setRecvDock("0");
        if (!receiptContainerHeaderService.updateById(receiptContainerHeader)){
            throw new ServiceException("更新库位失败");
        }

        //把库位编码赋到该入库组盘头表下的所有明细
        LambdaUpdateWrapper<ReceiptContainerDetail> lambda = Wrappers.lambdaUpdate();
        lambda.eq(ReceiptContainerDetail::getReceiptContainerId, receiptContainerHeader.getId())
                .set(ReceiptContainerDetail::getLocationCode, locationCode);
        if (!receiptContainerDetailService.update(lambda)){throw new ServiceException("更新库位编码到入库组盘明细失败");}

        ReceiptDetail oldReceiptDetail = receiptDetailService.getById(receiptContainerDetail.getReceiptDetailId());
        if (!oldReceiptDetail.getProcessStamp().equals("200")) {
            ReceiptDetail receiptDetail = receiptDetailService.queryflow(oldReceiptDetail);
            //更新入库单详情状态
            if (!receiptDetailService.updateById(receiptDetail)){ throw new ServiceException("更新入库单详情失败");}
            //更新入库单头尾状态
            receiptDetailService.updateReceiptHeaderLastStatus(receiptDetail.getReceiptId());
        }

        return true;
    }

    /**
     * 取消定位
     * @param receiptContainerDetail 入库组盘明细
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult cancelPosition(ReceiptContainerDetail receiptContainerDetail){
        //查询入库组盘头
        ReceiptContainerHeader receiptContainerHeader = receiptContainerHeaderService.getById(receiptContainerDetail.getReceiptContainerId());
            if (!(receiptContainerHeader.getStatus().shortValue() == QuantityConstant.RECEIPT_CONTAINER_BUILD)){
            throw new ServiceException("组盘已生成任务不能取消定位");
        }
        String locationCode = receiptContainerHeader.getToLocation();
        if(StringUtils.isEmpty(locationCode)) {
            throw new ServiceException("组盘没有定位,不需要取消定位");
        }
        //将入库组盘头表中的而库位编码赋值null
        receiptContainerHeader.setToLocation("");
        if (!receiptContainerHeaderService.updateById(receiptContainerHeader)){
            throw new ServiceException("回滚入库组盘头失败");
        }

        //将入库组盘明细的库位修改为空
        LambdaQueryWrapper<ReceiptContainerDetail> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(ReceiptContainerDetail::getReceiptContainerId, receiptContainerDetail.getReceiptContainerId());
        List<ReceiptContainerDetail> receiptContainerDetailList = receiptContainerDetailService.list(lambdaQueryWrapper);
        for (ReceiptContainerDetail receiptContainerDetail2 : receiptContainerDetailList) {
            receiptContainerDetail2.setLocationCode("");
            if (!receiptContainerDetailService.updateById(receiptContainerDetail2)){
                 throw new ServiceException("回滚入库组盘明细失败");
            }
        }

        //回滚入库明细状态
        ReceiptDetail receiptDetail = receiptDetailService.getById(receiptContainerDetail.getReceiptDetailId());
        receiptDetail.setProcessStamp(QuantityConstant.RECEIPT_HEADER_POSITION.toString());
        if ( !receiptDetailService.updateById(receiptDetail)){
            throw new ServiceException("回滚入库明细状态失败");
        }

        locationService.updateStatus(locationCode, QuantityConstant.STATUS_LOCATION_EMPTY);
        receiptDetailService.updateReceiptHeaderLastStatus(receiptDetail.getReceiptId());

        return AjaxResult.success("取消定位成功");
    }

    /**
     * 查找定位规则
     * @param receiptContainerHeader 入库组盘头
     * @param receiptContainerDetail 入库组盘明细
     * @return
     */
    public String findPositionRule(ReceiptContainerHeader receiptContainerHeader, ReceiptContainerDetail receiptContainerDetail) {
        /* 定位规则*/
        String locatingRule = receiptContainerHeader.getLocatingRule();
        if (StringUtils.isEmpty(locatingRule)){
            locatingRule = receiptDetailService.getById(receiptContainerDetail.getReceiptDetailId()).getLocatingRule();
            //入库单明细定位规则不为空时执行
            if (StringUtils.isEmpty(locatingRule)){
                //入库单明细为空时,查询物料表中是否含有定位规则
                LambdaQueryWrapper<Material> materialLambda = Wrappers.lambdaQuery();
                materialLambda.eq(Material::getCode, receiptContainerDetail.getMaterialCode())
                        .eq(Material::getWarehouseCode,ShiroUtils.getWarehouseCode());
                Material material = materialService.getOne(materialLambda);
                locatingRule = material.getLocatingRule();

                if (StringUtils.isEmpty(locatingRule)){
                    //物料表中定位规则为空时,查询物料类别
                    LambdaQueryWrapper<MaterialType> materialTypeLambda = Wrappers.lambdaQuery();
                    materialTypeLambda.eq(MaterialType::getCode, material.getType())
                            .eq(MaterialType::getWarehouseCode,ShiroUtils.getWarehouseCode());
                    MaterialType materialType = materialTypeService.getOne(materialTypeLambda);
                    locatingRule = materialType.getLocatingRule();
                    if (StringUtils.isEmpty(locatingRule)){
                        //物料类别中定位规则为空时,查询入库首选项
                        LambdaQueryWrapper<ConfigValue> configValueLambda = Wrappers.lambdaQuery();
                        configValueLambda.eq(ConfigValue::getWarehouseCode, ShiroUtils.getWarehouseCode())
                                .eq(ConfigValue::getModuleType, "receipt")
                                .eq(ConfigValue::getRecordType, "入库首选项");
                        ConfigValue configValue = configValueService.getOne(configValueLambda);
                        LambdaQueryWrapper<ReceiptPreference> lambdaQueryWrapper = Wrappers.lambdaQuery();
                        lambdaQueryWrapper.eq(ReceiptPreference::getCode, configValue.getValue())
                                .eq(ReceiptPreference::getWarehouseCode,ShiroUtils.getWarehouseCode());
                        locatingRule = preferenceService.getOne(lambdaQueryWrapper).getLocationRule();
                    }
                }
            }
        }
        return locatingRule;
    }
}