自动化立体仓库 - WMS系统
CTU预调度功能,更新为正式部署许可证,修改前端导出功能,打开Redis,数字孪生增加接口
9个文件已修改
282 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/DigitalTwinController.java 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/LocDetlController.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/DigitalTwinService.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/DigitalTwinServiceImpl.java 135 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/RedisConfig.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/RedisUtil.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/WcsController.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/license.lic 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/DigitalTwinController.java
@@ -1,16 +1,20 @@
package com.zy.asrs.controller;
import com.core.common.R;
import com.zy.asrs.entity.LocChartPie;
import com.zy.asrs.entity.LocDetl;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.entity.digitaltwin.*;
import com.zy.asrs.mapper.ReportQueryMapper;
import com.zy.asrs.service.DigitalTwinService;
import com.zy.common.web.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -20,14 +24,8 @@
    @Resource
    private DigitalTwinService digitalTwinService;
    /**
     * 查询所有库位状态和物料-二机床信息化数字孪生用
     */
    @RequestMapping(value = "/getAllLocations")
    public R getAllLocations(){
        return digitalTwinService.getAllLocations();
    }
    @Autowired
    private ReportQueryMapper reportQueryMapper;
    /**
     * 数据总览
@@ -328,5 +326,26 @@
//        return R.ok().add(dtLocDetailVoList);
    }
    @RequestMapping(value = "/getAllLocations")
    public R getAllLocations() {
        return digitalTwinService.getAllLocations();
    }
    /** * 查询在库数量等信息 */
    @RequestMapping(value = "/getLocalInfo")
    public LocChartPie getLocalInfo() {
        LocChartPie locUseRate = reportQueryMapper.getLocUseRate();
        return locUseRate;
    }
    /**
     * 查询所有库的库存明细
     */
    @RequestMapping(value = "/getLocalDetal")
    public R getLocalDetal() throws IOException {
        return R.ok(digitalTwinService.getLocalDetal());
    }
}
src/main/java/com/zy/asrs/controller/LocDetlController.java
@@ -298,15 +298,16 @@
        List<LocDetl> list = locDetlService.selectList(wrapper);
        List<AbnormalLocDetlParam> result = new ArrayList<>();
        Page<LocDetl> groupLocDetl = locDetlService.getStockStatis2(toPage(1, 10000, param, LocDetl.class));
        for (LocDetl locDetl : groupLocDetl.getRecords()) {
        // 使用完整的明细数据,而不是分组数据
        for (LocDetl locDetl : list) {
            AbnormalLocDetlParam abnormalLocDetlParam = new AbnormalLocDetlParam();
            Mat mat = matService.selectOne(new EntityWrapper<Mat>()
                    .eq("matnr", locDetl.getMatnr()));
            if (Cools.isEmpty(mat)) {
                continue;
            }
            if (!Cools.isEmpty(mat                                                                          .getStoreMax()) || !Cools.isEmpty(mat.getStoreMin())) {
            // 设置基本信息(无论是否异常)
                abnormalLocDetlParam.setStoreMax(mat.getStoreMax());
                abnormalLocDetlParam.setStoreMaxDate(mat.getStoreMaxDate());
                abnormalLocDetlParam.setStoreMin(mat.getStoreMin());
@@ -316,23 +317,34 @@
                abnormalLocDetlParam.setSpecs(mat.getSpecs());
                abnormalLocDetlParam.setBatch(locDetl.getBatch());
//                SimpleDateFormat simple = new SimpleDateFormat("yyyyMMdd");
//                Date maxDate = simple.parse(locDetl.getBatch());
//                long time = maxDate.getTime();
//                Date now = new Date();
//                long time1 = now.getTime();
//                abnormalLocDetlParam.setNowTime((int) ((time1 - time) / (1000 * 60 * 60 * 24)));
            // 设置导出需要的其他字段
            abnormalLocDetlParam.setLocNo(locDetl.getLocNo());
            abnormalLocDetlParam.setZpallet(locDetl.getZpallet());
            abnormalLocDetlParam.setOrderNo(locDetl.getOrderNo());
            abnormalLocDetlParam.setModiTime(locDetl.getModiTime());
                if (!Cools.isEmpty(mat.getStoreMax()) && locDetl.getAnfme() > mat.getStoreMax()) {
                    result.add(abnormalLocDetlParam);
                } else if (!Cools.isEmpty(mat.getStoreMin()) && locDetl.getAnfme() < mat.getStoreMin()) {
            // 计算库龄(实际在库天数)
            if (locDetl.getAppeTime() != null) {
                long diff = System.currentTimeMillis() - locDetl.getAppeTime().getTime();
                int days = (int) (diff / (1000 * 60 * 60 * 24));
                abnormalLocDetlParam.setNowTime(days);
            }
            // 确保所有字段都有值,避免空值导致导出异常
            if (abnormalLocDetlParam.getLocNo() == null) abnormalLocDetlParam.setLocNo("");
            if (abnormalLocDetlParam.getZpallet() == null) abnormalLocDetlParam.setZpallet("");
            if (abnormalLocDetlParam.getOrderNo() == null) abnormalLocDetlParam.setOrderNo("");
            if (abnormalLocDetlParam.getSpecs() == null) abnormalLocDetlParam.setSpecs("");
            // 总是添加到结果列表
                    result.add(abnormalLocDetlParam);
                }
            }
        }
        return R.ok(exportSupport(result, fields));
    }
    @RequestMapping(value = "/locDetl/selectOwner/list/auth")
    @ManagerAuth
    public R selectOwnerlist(@RequestParam(defaultValue = "1")Integer curr,
src/main/java/com/zy/asrs/service/DigitalTwinService.java
@@ -4,13 +4,9 @@
import com.zy.asrs.entity.digitaltwin.*;
import java.util.List;
import java.util.Map;
public interface DigitalTwinService {
    /**
     * 查询所有库位状态和物料-二机床信息化数字孪生用
     */
    R getAllLocations();
    /**
     * 总览:总库位、已用库位、剩余库位、今日出库、今日入库、剩余库位
@@ -77,4 +73,16 @@
    void locNumCount();
    DtEquipmentVo equipment(String areaId);
    /**
     * 查询所有库位状态和物料-二机床信息化数字孪生用
     */
    R getAllLocations();
    List<Map<String, Object>> getLocalDetal();
}
src/main/java/com/zy/asrs/service/impl/DigitalTwinServiceImpl.java
@@ -11,21 +11,20 @@
import com.zy.asrs.entity.mes.StockDetl;
import com.zy.asrs.mapper.DigitalTwinMapper;
import com.zy.asrs.mapper.LocCountMapper;
import com.zy.asrs.mapper.LocDetlMapper;
import com.zy.asrs.service.BasCrnpService;
import com.zy.asrs.service.DigitalTwinService;
import com.zy.asrs.service.LocDetlService;
import com.zy.asrs.service.LocMastService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
@Service
@@ -35,33 +34,8 @@
    private DigitalTwinMapper digitalTwinMapper;
    @Resource
    private LocCountMapper locCountMapper;
    @Override
    public R getAllLocations() {
        List<AllLocationsVo> allLocationsVos = new ArrayList<>();
        List<LocMast> locMastList = locMastService.selectList(new EntityWrapper<>());
        locMastList.forEach(locMast -> {
            AllLocationsVo allLocationsVo = new AllLocationsVo();
            allLocationsVo.setLocNo(locMast.getLocNo());
            String locSts = locMast.getLocSts();
            allLocationsVo.setLocSts(locSts);
            // 有库存
            if (locSts.equals("F") || locSts.equals("P") || locSts.equals("Q") || locSts.equals("R")) {
                List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", locMast.getLocNo()));
                if (!locDetls.isEmpty()) {
                    List<AllLocationsVo.LocDetl> locDetlList = locDetls.stream().map(locDetl -> {
                                AllLocationsVo.LocDetl locDetl1 = new AllLocationsVo.LocDetl();
                                BeanUtils.copyProperties(locDetl, locDetl1);
                                return locDetl1;
                            }
                    ).collect(Collectors.toList());
                    allLocationsVo.setLocDetls(locDetlList);
                }
            }
            allLocationsVos.add(allLocationsVo);
        });
        return R.ok(allLocationsVos);
    }
    @Autowired
    private LocDetlMapper locDetlMapper;
    /**
     * 总览:总库位、已用库位、剩余库位、今日出库、今日入库、剩余库位
@@ -106,14 +80,36 @@
            endTime = now;
        } else {
            SimpleDateFormat sdf =
                    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            SimpleDateFormat sdf;
            try {
                // 尝试解析yyyyMMdd格式
                if (startDate.length() == 8 && endDate.length() == 8) {
                    sdf = new SimpleDateFormat("yyyyMMdd");
                startTime  = sdf.parse(startDate);
                endTime = sdf.parse(endDate);
                    // 设置结束时间为当天的23:59:59.999
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(endTime);
                    calendar.set(Calendar.HOUR_OF_DAY, 23);
                    calendar.set(Calendar.MINUTE, 59);
                    calendar.set(Calendar.SECOND, 59);
                    calendar.set(Calendar.MILLISECOND, 999);
                    endTime = calendar.getTime();
                } else {
                    // 尝试解析yyyy-MM-dd HH:mm:ss.SSS格式
                    sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                    startTime = sdf.parse(startDate);
                    endTime = sdf.parse(endDate);
                }
            } catch (ParseException e) {
                e.printStackTrace();
                // 解析失败时使用默认的7天时间范围
                Date now = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(now);
                calendar.add(Calendar.DAY_OF_MONTH, -7);
                startTime = calendar.getTime();
                endTime = now;
            }
        }
        List<DtOrderVo> dbOrder = digitalTwinMapper.recentOrder(startTime, endTime);
@@ -146,14 +142,36 @@
            endTime = now;
        } else {
            SimpleDateFormat sdf =
                    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            SimpleDateFormat sdf;
            try {
                // 尝试解析yyyyMMdd格式
                if (startDate.length() == 8 && endDate.length() == 8) {
                    sdf = new SimpleDateFormat("yyyyMMdd");
                startTime  = sdf.parse(startDate);
                endTime = sdf.parse(endDate);
                    // 设置结束时间为当天的23:59:59.999
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(endTime);
                    calendar.set(Calendar.HOUR_OF_DAY, 23);
                    calendar.set(Calendar.MINUTE, 59);
                    calendar.set(Calendar.SECOND, 59);
                    calendar.set(Calendar.MILLISECOND, 999);
                    endTime = calendar.getTime();
                } else {
                    // 尝试解析yyyy-MM-dd HH:mm:ss.SSS格式
                    sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                    startTime = sdf.parse(startDate);
                    endTime = sdf.parse(endDate);
                }
            } catch (ParseException e) {
                e.printStackTrace();
                // 解析失败时使用默认的7天时间范围
                Date now = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(now);
                calendar.add(Calendar.DAY_OF_MONTH, -7);
                startTime = calendar.getTime();
                endTime = now;
            }
        }
@@ -371,4 +389,47 @@
    // endregion
    @Override
    public R getAllLocations() {
        List<AllLocationsVo> allLocationsVos = new ArrayList<>();
        List<LocMast> locMastList = locMastService.selectList(new EntityWrapper<>());
        locMastList.forEach(locMast -> {
            AllLocationsVo allLocationsVo = new AllLocationsVo();
            allLocationsVo.setLocNo(locMast.getLocNo());
            String locSts = locMast.getLocSts();
            allLocationsVo.setLocSts(locSts);
            // 有库存
            if (locSts.equals("F") || locSts.equals("P") || locSts.equals("Q") || locSts.equals("R")) {
                List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", locMast.getLocNo()));
                if (!locDetls.isEmpty()) {
                    List<AllLocationsVo.LocDetl> locDetlList = locDetls.stream().map(locDetl -> {
                                AllLocationsVo.LocDetl locDetl1 = new AllLocationsVo.LocDetl();
                                BeanUtils.copyProperties(locDetl, locDetl1);
                                return locDetl1;
                            }
                    ).collect(Collectors.toList());
                    allLocationsVo.setLocDetls(locDetlList);
                }
            }
            allLocationsVos.add(allLocationsVo);
        });
        return R.ok(allLocationsVos);
    }
    public List<Map<String, Object>> getLocalDetal() {
        List<LocDetl> locDetls = locDetlMapper.selectList(new EntityWrapper<>());
        List<Map<String, Object>> result = new ArrayList<>();
        for (LocDetl locDetl : locDetls) {
            Map<String, Object> item = new HashMap<>();
            item.put("zpallet", locDetl.getZpallet());
            item.put("anfme", locDetl.getAnfme());
            item.put("matnr", locDetl.getMatnr());
            item.put("maktx", locDetl.getMaktx());
            result.add(item);
        }
        return result;
    }
}
src/main/java/com/zy/common/config/RedisConfig.java
@@ -4,7 +4,9 @@
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
@@ -14,8 +16,8 @@
 * Redis配置类
 * Created by vincent on 2019-12-23
 */
//@Configuration
//@EnableCaching // 开启数据缓存机制
@Configuration
@EnableCaching // 开启数据缓存机制
public class RedisConfig extends CachingConfigurerSupport {
src/main/java/com/zy/common/utils/RedisUtil.java
@@ -2,6 +2,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
@@ -13,7 +14,7 @@
 * redisTemplate封装
 *
 */
//@Component
@Component
public class RedisUtil {
    @Autowired
src/main/java/com/zy/common/web/WcsController.java
@@ -1,5 +1,8 @@
package com.zy.common.web;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.Cools;
@@ -7,22 +10,29 @@
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.EmptyPlateOutParam;
import com.zy.asrs.entity.rcs.RcsReturn;
import com.zy.asrs.entity.result.FindLocNoAttributeVo;
import com.zy.asrs.service.*;
import com.zy.asrs.service.impl.RcsServiceImpl;
import com.zy.common.CodeRes;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.StartupDto;
import com.zy.common.service.CommonService;
import com.zy.common.utils.RedisUtil;
import com.zy.common.web.param.SearchLocParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import static com.zy.asrs.service.impl.RcsServiceImpl.sendPost;
/**
 * Created by vincent on 2020/10/30
@@ -50,13 +60,23 @@
    private RowLastnoService rowLastnoService;
    @Autowired
    private WorkService workService;
    @Autowired
    private RedisUtil redisUtil;
    @Value("${hik.url}")
    private String HIK_URL;
    private static final String IS_START_PRE_SCHEDULE = "schedule:check";
    // TODO:称重、拍照上报存储,CTU料箱运转
    @PostMapping("/pakin/loc/v1")
    @ResponseBody
    public synchronized R getLocNo(@RequestBody SearchLocParam param) {
        log.info("收到WCS入库接口请求====>>入参:{}", param);
        PreScheduling();
        if (Cools.isEmpty(param.getIoType())) {
            return R.error("入出库类型不能为空");
        }
@@ -313,4 +333,27 @@
        return dto;
    }
    public void PreScheduling(){
        if (redisUtil.get(IS_START_PRE_SCHEDULE)!=null && redisUtil.get(IS_START_PRE_SCHEDULE).equals("T")){
            return;
        }else {
            redisUtil.set(IS_START_PRE_SCHEDULE, "T",70);
        }
        String url = "api/robot/controller/task/pretask";
        String URL = HIK_URL + url;
        JSONObject preSchedule = new JSONObject();
        preSchedule.put("siteCode", "106");
        preSchedule.put("nextTaskTime", "70");
        preSchedule.put("robotType", "18,25");
        preSchedule.put("taskCount", 3);
        String response = sendPost(URL, JSONObject.toJSONString(preSchedule));
        if (!StringUtils.isEmpty(response) && response.contains("code")){
            log.info("预调度成功{}", preSchedule);
        } else {
            log.info("预调度失败{}", preSchedule);
        }
    }
}
src/main/resources/application-dev.yml
@@ -50,7 +50,7 @@
#License相关配置
license:
  subject: jgasrs
  subject: jnejc-djwms
  publicAlias: publicCert
  storePass: public_zhongyang_123456789
  licensePath: license.lic
src/main/resources/license.lic
Binary files differ