Jelajahi Sumber

物资-临期提醒

huangguoce 1 hari lalu
induk
melakukan
4a28869e19
12 mengubah file dengan 343 tambahan dan 16 penghapusan
  1. 21 0
      jeeplus-api/jeeplus-system-api/src/main/java/com/jeeplus/flowable/factory/PsiManagementApiFallbackFactory.java
  2. 15 0
      jeeplus-api/jeeplus-system-api/src/main/java/com/jeeplus/flowable/feign/IPsiManagementApi.java
  3. 4 0
      jeeplus-common/jeeplus-common-core/src/main/java/com/jeeplus/common/constant/AppNameConstants.java
  4. 2 2
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/collect/service/PsiCollectService.java
  5. 24 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/feign/PsiManagementApiImpl.java
  6. 0 3
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/materialType/service/PsiMaterialTypeForTreeDataService.java
  7. 16 3
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/psiWareHouse/controller/PsiWareHouseController.java
  8. 6 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/psiWareHouse/mapper/PsiWareHouseBasicMapper.java
  9. 23 0
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/psiWareHouse/mapper/xml/PsiWareHouseBasicMapper.xml
  10. 209 4
      jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/psiWareHouse/service/PsiWareHouseBasicService.java
  11. 9 0
      jeeplus-modules/jeeplus-xxl-job-executor-sample/src/main/java/com/xxl/job/executor/feign/PsiManagementFeignApi.java
  12. 14 4
      jeeplus-modules/jeeplus-xxl-job-executor-sample/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java

+ 21 - 0
jeeplus-api/jeeplus-system-api/src/main/java/com/jeeplus/flowable/factory/PsiManagementApiFallbackFactory.java

@@ -0,0 +1,21 @@
+package com.jeeplus.flowable.factory;
+
+import com.jeeplus.flowable.feign.IPsiManagementApi;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.openfeign.FallbackFactory;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class PsiManagementApiFallbackFactory implements FallbackFactory<IPsiManagementApi> {
+
+    @Override
+    public IPsiManagementApi create(Throwable cause) {
+        log.error("psi-management service call failed:{}", cause.getMessage());
+        return new IPsiManagementApi() {
+            @Override
+            public void nearExpiryList() {
+            }
+        };
+    }
+}

+ 15 - 0
jeeplus-api/jeeplus-system-api/src/main/java/com/jeeplus/flowable/feign/IPsiManagementApi.java

@@ -0,0 +1,15 @@
+package com.jeeplus.flowable.feign;
+
+import com.jeeplus.common.constant.AppNameConstants;
+import com.jeeplus.flowable.factory.PsiManagementApiFallbackFactory;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@FeignClient(contextId = "psiManagementApi", name = AppNameConstants.APP_PSI_MANAGEMENT_MODULES, fallbackFactory = PsiManagementApiFallbackFactory.class)
+public interface IPsiManagementApi {
+
+    String BASE_URL = "/feign/psi/management/wareHouse";
+
+    @GetMapping(value = BASE_URL + "/nearExpiryList")
+    void nearExpiryList();
+}

+ 4 - 0
jeeplus-common/jeeplus-common-core/src/main/java/com/jeeplus/common/constant/AppNameConstants.java

@@ -45,4 +45,8 @@ public interface AppNameConstants {
      * 培训模块
      */
     String APP_CONSULT_MODULES = "jeeplus-consultancy";
+    /**
+     * psi管理模块
+     */
+    String APP_PSI_MANAGEMENT_MODULES = "jeeplus-psi-management";
 }

+ 2 - 2
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/collect/service/PsiCollectService.java

@@ -451,7 +451,7 @@ public class PsiCollectService {
                     String warnInfo = String.join("、", warnInfoList);
                     SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                     String day = format.format(new Date());
-                    String title = "管理员发起了 ["+ warnInfo +"] [库存提醒]";
+                    String title = "管理员发起了 ["+ warnInfo +"] [物资库存提醒]";
                     //向多个用户发起通知
                     List<UserDTO> usersInfo = psiWareHouseDetailedMapper.getUsersInfo();
                     //获取目前领用流程的taskid,根据procInsId去查taskId
@@ -465,7 +465,7 @@ public class PsiCollectService {
                             map.put("taskId",uuid);
                             map.put("title",title);
                             map.put("defId",dto.getId());
-                            map.put("taskName","进销存库存提醒");
+                            map.put("taskName","物资库存提醒");
                             map.put("createUser","管理员");
                             map.put("createTime",day);
                             map.put("noticeName",userDTO1.getLoginName());

+ 24 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/feign/PsiManagementApiImpl.java

@@ -0,0 +1,24 @@
+package com.jeeplus.psimanage.feign;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jeeplus.flowable.feign.IPsiManagementApi;
+import com.jeeplus.psimanage.psiWareHouse.service.PsiWareHouseBasicService;
+import com.jeeplus.psimanage.psiWareHouse.service.dto.PsiWareHouseDto;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@RestController
+public class PsiManagementApiImpl implements IPsiManagementApi {
+
+    @Resource
+    private PsiWareHouseBasicService psiWareHouseBasicService;
+
+    @Override
+    public void nearExpiryList() {
+        Page<PsiWareHouseDto> page = new Page<>();
+        page.setCurrent(1);
+        page.setSize(-1);
+        psiWareHouseBasicService.nearExpiryList(page, new PsiWareHouseDto());
+    }
+}

+ 0 - 3
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/materialType/service/PsiMaterialTypeForTreeDataService.java

@@ -98,9 +98,6 @@ public class PsiMaterialTypeForTreeDataService extends TreeService<PsiMaterialTy
      * @param root    根节点, 为空抛出空指针异常
      * @param allList 所有需要参与构造为树的列表
      * @param extId   需要排除在树之外的节点(子节点一并被排除)
-     * @return java.util.List<T>
-     * @Author 滕鑫源
-     * @Date 2020/10/23 17:04
      **/
     public List <PsiMaterialTypeInfo> formatListToTreeForType (PsiMaterialTypeInfo root, List <PsiMaterialTypeInfo> allList, String extId, String type) {
         String rootId = root.getId ( );

+ 16 - 3
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/psiWareHouse/controller/PsiWareHouseController.java

@@ -198,11 +198,24 @@ public class PsiWareHouseController {
         return ResponseEntity.ok(iPage);
     }
 
+    /**
+     * 查询所有库存数据,无限制
+     * @param dto
+     * @return
+     */
+    @ApiOperation(value = "查询所有库存数据,无限制")
+    @GetMapping("/getAllData")
+    public ResponseEntity<IPage<PsiWareHouseDto>> getAllData(Page<PsiWareHouseDto> page, PsiWareHouseDto dto) throws Exception{
+        IPage<PsiWareHouseDto> iPage = basicService.getAllData(page, dto);
+        return ResponseEntity.ok(iPage);
+    }
+
+
+
     @ApiOperation(value = "即将过期物资查询")
     @GetMapping("/nearExpiryList")
-    public ResponseEntity<IPage<PsiWareHouseDto>> nearExpiryList(Page<PsiWareHouseDto> page, PsiWareHouseDto dto) {
-        IPage<PsiWareHouseDto> iPage = basicService.nearExpiryList(page, dto);
-        return ResponseEntity.ok(iPage);
+    public void nearExpiryList(Page<PsiWareHouseDto> page, PsiWareHouseDto dto) {
+       basicService.nearExpiryList(page, dto);
     }
 
 

+ 6 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/psiWareHouse/mapper/PsiWareHouseBasicMapper.java

@@ -1,5 +1,6 @@
 package com.jeeplus.psimanage.psiWareHouse.mapper;
 
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
@@ -57,11 +58,16 @@ public interface PsiWareHouseBasicMapper extends BaseMapper<PsiWareHouseBasic> {
 
     IPage<PsiWareHouseDto> summaryList2(Page<PsiWareHouseDto> page,@Param(Constants.WRAPPER) QueryWrapper<PsiWareHouseDto> queryWrapper);
 
+    @InterceptorIgnore(tenantLine = "true")
     IPage<PsiWareHouseDto> getByProduceDateAndName(Page<PsiWareHouseDto> page,@Param(Constants.WRAPPER) QueryWrapper<PsiWareHouseDto> queryWrapper);
 
 
     IPage<PsiWareHouseDto> getByProduceDateNotMerge(Page<PsiWareHouseDto> page,@Param(Constants.WRAPPER) QueryWrapper<PsiWareHouseDto> queryWrapper);
 
+    @InterceptorIgnore(tenantLine = "true")
+    IPage<PsiWareHouseDto> getAllData(Page<PsiWareHouseDto> page,@Param(Constants.WRAPPER) QueryWrapper<PsiWareHouseDto> queryWrapper);
+
+    @InterceptorIgnore(tenantLine = "true")
     IPage<PsiWareHouseDto> nearExpiryList(Page<PsiWareHouseDto> page, @Param("dto") PsiWareHouseDto dto);
 
     IPage<PsiWareHouseDto> wareHouseHistoryList(Page<PsiWareHouseDto> page,@Param(Constants.WRAPPER) QueryWrapper<PsiWareHouseDto> queryWrapper);

+ 23 - 0
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/psiWareHouse/mapper/xml/PsiWareHouseBasicMapper.xml

@@ -270,6 +270,29 @@
 		GROUP BY a.trade_name,a.ware_house_type,a.produce_date
 		ORDER BY a.produce_date asc
 	</select>
+	<select id="getAllData"
+			resultType="com.jeeplus.psimanage.psiWareHouse.service.dto.PsiWareHouseDto">
+		SELECT
+			a.id,
+			a.produce_date as produce_date,
+			a.trade_name,
+			a.spec,
+			a.company,
+			a.current_inventory,
+			a.shelf_life,
+			a.shelf_life_unit,
+			pmwd.warn_num,
+			pmwd.warn_flag
+		FROM
+			psi_management_warehouse_detailed a
+				LEFT JOIN psi_management_warehouse_basics bas on a.basic_id = bas.id
+				LEFT JOIN psi_management_warehouse_detailed pmwd on bas.id = pmwd.basic_id
+				left join psi_management_type c on a.ware_house_type = c.id
+			${ew.customSqlSegment}
+
+		GROUP BY a.trade_name,a.ware_house_type,a.produce_date
+		ORDER BY a.produce_date asc
+	</select>
 
 	<select id="nearExpiryList"
 			resultType="com.jeeplus.psimanage.psiWareHouse.service.dto.PsiWareHouseDto">

+ 209 - 4
jeeplus-modules/jeeplus-psi-management/src/main/java/com/jeeplus/psimanage/psiWareHouse/service/PsiWareHouseBasicService.java

@@ -43,6 +43,9 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
 import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -1105,17 +1108,137 @@ public class PsiWareHouseBasicService {
         return wareHouseDtoIPage;
     }
 
-    public IPage<PsiWareHouseDto> nearExpiryList(Page<PsiWareHouseDto> page, PsiWareHouseDto dto) {
-        IPage<PsiWareHouseDto> iPage = basicMapper.nearExpiryList(page, dto);
+    /**
+     * 根据库存的保质期和生产日期,进行临期规则筛选
+     * @param page
+     * @param dto
+     */
+    public void nearExpiryList(Page<PsiWareHouseDto> page, PsiWareHouseDto dto) {
+        Page<PsiWareHouseDto> queryPage = new Page<>();
+        queryPage.setCurrent(1);
+        queryPage.setSize(-1);
+        IPage<PsiWareHouseDto> iPage = basicMapper.nearExpiryList(queryPage, dto);
+        List<PsiWareHouseDto> list = new ArrayList<>();
+        LocalDate today = LocalDate.now(ZoneId.systemDefault());
         iPage.getRecords().forEach(item -> {
-
+            if (!canCheckNearExpiry(item)) {
+                return;
+            }
+            Integer shelfLifeValue = parseShelfLifeValue(item.getShelfLife());
+            if (shelfLifeValue == null) {
+                return;
+            }
+            LocalDate produceDate = toLocalDate(item.getProduceDate());
+            LocalDate expiryDate = calculateExpiryDate(produceDate, shelfLifeValue, item.getShelfLifeUnit());
+            if (expiryDate == null) {
+                return;
+            }
+            long totalDays = ChronoUnit.DAYS.between(produceDate, expiryDate);
+            long remainingDays = ChronoUnit.DAYS.between(today, expiryDate);
+            if (!shouldIncludeNearExpiry(totalDays, remainingDays)) {
+                return;
+            }
+            item.setExpiryDate(Date.from(expiryDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
+            item.setRemainingDays((int) remainingDays);
+            list.add(item);
         });
-        return iPage;
+        if(CollectionUtil.isNotEmpty(list)){
+            String warnInfo = list.stream()
+                    .map(item -> item.getTradeName())
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.joining("、"));
+            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+            String day = format.format(new Date());
+            String title = "管理员发起了 ["+ warnInfo +"] [物资临期提醒]";
+            //向多个用户发起通知
+            List<UserDTO> usersInfo = psiDetailedMapper.getUsersInfo();
+            //获取目前领用流程的taskid,根据procInsId去查taskId
+            String uuid = "";
+            if (null != usersInfo) {
+                for (UserDTO userDTO1 : usersInfo) {
+                    uuid = UUID.randomUUID().toString();
+                    //发送通知
+                    Map<String ,String > map = new HashMap<>();
+                    map.put("taskId",uuid);
+                    map.put("title",title);
+                    map.put("defId",dto.getId());
+                    map.put("taskName","物资临期提醒");
+                    map.put("createUser","管理员");
+                    map.put("createTime",day);
+                    map.put("noticeName",userDTO1.getLoginName());
+                    map.put("noticeId",userDTO1.getId());
+                    map.put("createById","1");
+                    flowTaskService.add(map);
+                }
+            }
+        }
     }
 
     /**
      * 列表查询
      */
+    private boolean canCheckNearExpiry(PsiWareHouseDto item) {
+        return item != null
+                && item.getProduceDate() != null
+                && StringUtils.isNotBlank(item.getShelfLife())
+                && StringUtils.isNotBlank(item.getShelfLifeUnit());
+    }
+
+    private Integer parseShelfLifeValue(String shelfLife) {
+        try {
+            BigDecimal value = new BigDecimal(shelfLife.trim()).stripTrailingZeros();
+            if (value.scale() > 0 || value.compareTo(BigDecimal.ZERO) <= 0) {
+                return null;
+            }
+            return value.intValueExact();
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    private LocalDate toLocalDate(Date date) {
+        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+    }
+
+    private LocalDate calculateExpiryDate(LocalDate produceDate, Integer shelfLife, String shelfLifeUnit) {
+        String unit = shelfLifeUnit == null ? "" : shelfLifeUnit.trim();
+        if (unit.contains("年")) {
+            return produceDate.plusYears(shelfLife);
+        }
+        if (unit.contains("月")) {
+            return produceDate.plusMonths(shelfLife);
+        }
+        if (unit.contains("天") || unit.contains("日")) {
+            return produceDate.plusDays(shelfLife);
+        }
+        return null;
+    }
+
+    private boolean shouldIncludeNearExpiry(long totalDays, long remainingDays) {
+        if (totalDays <= 0 || remainingDays < 0) {
+            return false;
+        }
+        if (totalDays <= 30) {
+            return remainingDays * 3 <= totalDays;
+        }
+        return remainingDays * 4 <= totalDays
+                || remainingDays == 30
+                || remainingDays == 60
+                || remainingDays == 90;
+    }
+
+    private List<PsiWareHouseDto> buildNearExpiryPageRecords(List<PsiWareHouseDto> list, long current, long size) {
+        if (size <= 0) {
+            return list;
+        }
+        long start = (current - 1) * size;
+        if (start >= list.size()) {
+            return new ArrayList<>();
+        }
+        long end = Math.min(start + size, list.size());
+        return new ArrayList<>(list.subList((int) start, (int) end));
+    }
+
     public IPage<PsiWareHouseDto> getByProduceDateNotMerge(Page<PsiWareHouseDto> page , PsiWareHouseDto dto) throws Exception{
         QueryWrapper<PsiWareHouseDto> queryWrapper = QueryWrapperGenerator.buildQueryCondition(dto, PsiWareHouseDto.class);
 
@@ -1181,6 +1304,88 @@ public class PsiWareHouseBasicService {
     }
 
 
+    public IPage<PsiWareHouseDto> getAllData(Page<PsiWareHouseDto> page , PsiWareHouseDto dto) throws Exception{
+        QueryWrapper<PsiWareHouseDto> queryWrapper = QueryWrapperGenerator.buildQueryCondition(dto, PsiWareHouseDto.class);
+
+        queryWrapper.eq("a.del_flag", "0");
+
+        if (StringUtils.isNotEmpty(dto.getTradeName())) {
+            queryWrapper.like("a.trade_name", dto.getTradeName());
+        }
+        queryWrapper.and(wq ->{
+            wq.eq("bas.`status`","0")
+                    .or()
+                    .eq("bas.`status`","5");
+        });
+
+        //入库类型
+        if (StringUtils.isNotEmpty(dto.getWareHouseType())) {
+            queryWrapper.eq("c.id", dto.getWareHouseType());
+        }
+
+        //生产日期
+        if (dto.getProduceDate() != null) {
+            queryWrapper.eq("a.produce_date", dto.getProduceDate());
+        }
+
+        if (StringUtils.isNotEmpty(dto.getSupplierId())) {
+            List<PsiWareHouseDetailed> wareHouseDetaileds = psiDetailedMapper.selectList(new LambdaQueryWrapper<PsiWareHouseDetailed>().eq(PsiWareHouseDetailed::getSupplierId, dto.getSupplierId()));
+            if (CollectionUtil.isNotEmpty(wareHouseDetaileds)) {
+                List<String> containsIds = wareHouseDetaileds.stream().map(PsiWareHouseDetailed::getId).collect(Collectors.toList());
+                if (CollectionUtil.isNotEmpty(containsIds)) {
+                    queryWrapper.in("a.id", containsIds);
+                } else {
+                    return new Page<>();
+                }
+            } else {
+                return new Page<>();
+            }
+        }
+        LocalDate today = LocalDate.now(ZoneId.systemDefault());
+        IPage<PsiWareHouseDto> wareHouseDtoIPage = basicMapper.getAllData(page, queryWrapper);
+        wareHouseDtoIPage.getRecords().forEach(item -> {
+            // 将小数点后无效的0删除
+            // 总量  格式化
+            if (StringUtils.isNotBlank(item.getAllNumber())) {
+                String s = convertByBigDecimal(item.getAllNumber());
+                item.setAllNumber(s);
+            }
+            //领用量  格式化
+            if (StringUtils.isNotBlank(item.getBorrowNumber())) {
+                String s = convertByBigDecimal(item.getBorrowNumber());
+                item.setBorrowNumber(s);
+            }
+            //剩余量  格式化
+            if (StringUtils.isNotBlank(item.getTradeNumber())) {
+                String s = convertByBigDecimal(item.getTradeNumber());
+                item.setTradeNumber(s);
+            }
+            //提醒数量  格式化
+            if (StringUtils.isNotBlank(item.getWarnNum())) {
+                String s = convertByBigDecimal(item.getWarnNum());
+                item.setWarnNum(s);
+            }
+
+            if (!canCheckNearExpiry(item)) {
+                return;
+            }
+            Integer shelfLifeValue = parseShelfLifeValue(item.getShelfLife());
+            if (shelfLifeValue == null) {
+                return;
+            }
+            LocalDate produceDate = toLocalDate(item.getProduceDate());
+            LocalDate expiryDate = calculateExpiryDate(produceDate, shelfLifeValue, item.getShelfLifeUnit());
+            if (expiryDate == null) {
+                return;
+            }
+            long totalDays = ChronoUnit.DAYS.between(produceDate, expiryDate);
+            long remainingDays = ChronoUnit.DAYS.between(today, expiryDate);
+            item.setExpiryDate(Date.from(expiryDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
+            item.setRemainingDays((int) remainingDays);
+        });
+        return wareHouseDtoIPage;
+    }
+
 
     // 去除小数点后无效的0
     public String convertByBigDecimal(String value) {

+ 9 - 0
jeeplus-modules/jeeplus-xxl-job-executor-sample/src/main/java/com/xxl/job/executor/feign/PsiManagementFeignApi.java

@@ -0,0 +1,9 @@
+package com.xxl.job.executor.feign;
+
+import com.jeeplus.common.constant.AppNameConstants;
+import com.jeeplus.flowable.feign.IPsiManagementApi;
+import org.springframework.cloud.openfeign.FeignClient;
+
+@FeignClient(contextId = "psiManagementFeignApi", name = AppNameConstants.APP_PSI_MANAGEMENT_MODULES)
+public interface PsiManagementFeignApi extends IPsiManagementApi {
+}

+ 14 - 4
jeeplus-modules/jeeplus-xxl-job-executor-sample/src/main/java/com/xxl/job/executor/service/jobhandler/SampleXxlJob.java

@@ -5,10 +5,7 @@ import cn.hutool.extra.spring.SpringUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.TypeReference;
 import com.jeeplus.domain.*;
-import com.jeeplus.flowable.feign.IAssessApi;
-import com.jeeplus.flowable.feign.IFinanceApi;
-import com.jeeplus.flowable.feign.IFlowableApi;
-import com.jeeplus.flowable.feign.IHumanApi;
+import com.jeeplus.flowable.feign.*;
 import com.jeeplus.sys.feign.*;
 import com.jeeplus.sys.service.dto.UserDTO;
 import com.xxl.job.core.context.XxlJobHelper;
@@ -1204,4 +1201,17 @@ public class SampleXxlJob {
         }
     }
 
+
+    /**
+     * 查询即将过期的物资
+     */
+    @XxlJob("nearExpiryList")
+    public void nearExpiryList() {
+        try {
+            SpringUtil.getBean(IPsiManagementApi.class).nearExpiryList();
+        } catch (Exception e) {
+            logger.warn("调用失败,可能服务不存在", e);
+        }
+    }
+
 }