Commit a37453fbcf428d9bafb2b847e961e7d9bd7c3cdc

Authored by 杨鸣坤
1 parent 27a98db6

楚江ERP:校验申请日期是否超过规定值

... ... @@ -232,4 +232,21 @@ create table `tbl_spec_lock_delay_application`
232 232 `update_by` varchar(20) not null comment '更新人',
233 233 `create_time` datetime default now() comment '创建时间',
234 234 `update_time` datetime default now() comment '更新时间'
235   -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '锁价无规格操作申请单' ROW_FORMAT = DYNAMIC;
\ No newline at end of file
  235 +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '锁价无规格操作申请单' ROW_FORMAT = DYNAMIC;
  236 +
  237 +-- 节假日
  238 +DROP TABLE IF EXISTS `tbl_holidays`;
  239 +create table `tbl_holidays`
  240 +(
  241 + `id` varchar(32) primary key comment 'ID',
  242 + `year` int(4) NOT NULL COMMENT '年份',
  243 + `holiday_date` date NOT NULL COMMENT '日期',
  244 + `rest` TINYINT(1) COMMENT '是否休息(0-补班,1-休息)',
  245 + `holiday_name` varchar(50) COMMENT '节假日名称',
  246 + `create_by_id` varchar(32) not null comment '创建人ID',
  247 + `create_by` varchar(20) not null comment '创建人',
  248 + `update_by_id` varchar(32) not null comment '更新人ID',
  249 + `update_by` varchar(20) not null comment '更新人',
  250 + `create_time` datetime default now() comment '创建时间',
  251 + `update_time` datetime default now() comment '更新时间'
  252 +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '节假日' ROW_FORMAT = DYNAMIC;
\ No newline at end of file
... ...
... ... @@ -192,7 +192,7 @@ public class SpecLockDelayApplicationController extends DefaultBaseController {
192 192 @ApiOperation("新增")
193 193 @HasPermission({"entity:speclockdelayapplication:add"})
194 194 @PostMapping
195   - public InvokeResult<Void> create(@RequestBody CreateSpecLockDelayApplicationVo vo) {
  195 + public InvokeResult<Void> create(@RequestBody CreateSpecLockDelayApplicationVo vo) throws Exception {
196 196
197 197 specLockDelayApplicationService.create(vo);
198 198
... ... @@ -205,7 +205,7 @@ public class SpecLockDelayApplicationController extends DefaultBaseController {
205 205 @ApiOperation("修改")
206 206 @HasPermission({"entity:speclockdelayapplication:modify"})
207 207 @PutMapping
208   - public InvokeResult<Void> update(@RequestBody UpdateSpecLockDelayApplicationVo vo) {
  208 + public InvokeResult<Void> update(@RequestBody UpdateSpecLockDelayApplicationVo vo) throws Exception {
209 209
210 210 specLockDelayApplicationService.update(vo);
211 211
... ...
  1 +package com.lframework.xingyun.sc.entity;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.FieldFill;
  4 +import com.baomidou.mybatisplus.annotation.TableField;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import com.lframework.starter.web.core.dto.BaseDto;
  7 +import com.lframework.starter.web.core.entity.BaseEntity;
  8 +import lombok.Data;
  9 +
  10 +import java.time.LocalDate;
  11 +import java.time.LocalDateTime;
  12 +
  13 +/**
  14 + * <p>
  15 + * 节假日
  16 + * </p>
  17 + */
  18 +@Data
  19 +@TableName("tbl_holidays")
  20 +public class Holidays extends BaseEntity implements BaseDto {
  21 +
  22 + private static final long serialVersionUID = 1L;
  23 +
  24 + public static final String CACHE_NAME = "Holidays";
  25 +
  26 + /**
  27 + * ID
  28 + */
  29 + private String id;
  30 +
  31 + /**
  32 + * 年份
  33 + */
  34 + private Integer year;
  35 +
  36 + /**
  37 + * 日期
  38 + */
  39 + private LocalDate holidayDate;
  40 +
  41 + /**
  42 + * 是否休息(0-补班,1-休息)
  43 + */
  44 + private Boolean rest;
  45 +
  46 + /**
  47 + * 节假日名称
  48 + */
  49 + private String holidayName;
  50 +
  51 + /**
  52 + * 创建人ID
  53 + */
  54 + @TableField(fill = FieldFill.INSERT)
  55 + private String createById;
  56 +
  57 + /**
  58 + * 创建人
  59 + */
  60 + @TableField(fill = FieldFill.INSERT)
  61 + private String createBy;
  62 +
  63 + /**
  64 + * 更新人ID
  65 + */
  66 + @TableField(fill = FieldFill.INSERT_UPDATE)
  67 + private String updateById;
  68 +
  69 + /**
  70 + * 更新人
  71 + */
  72 + @TableField(fill = FieldFill.INSERT_UPDATE)
  73 + private String updateBy;
  74 +
  75 + /**
  76 + * 创建时间
  77 + */
  78 + @TableField(fill = FieldFill.INSERT)
  79 + private LocalDateTime createTime;
  80 +
  81 + /**
  82 + * 更新时间
  83 + */
  84 + @TableField(fill = FieldFill.INSERT_UPDATE)
  85 + private LocalDateTime updateTime;
  86 +
  87 +}
... ...
  1 +package com.lframework.xingyun.sc.impl;
  2 +
  3 +import cn.hutool.json.JSONArray;
  4 +import cn.hutool.json.JSONObject;
  5 +import com.lframework.starter.common.exceptions.impl.DefaultClientException;
  6 +import com.lframework.starter.common.utils.DateUtil;
  7 +import com.lframework.starter.common.utils.ObjectUtil;
  8 +import com.lframework.starter.web.core.impl.BaseMpServiceImpl;
  9 +import com.lframework.starter.web.core.utils.IdUtil;
  10 +import com.lframework.starter.web.core.utils.JsonUtil;
  11 +import com.lframework.xingyun.sc.entity.Holidays;
  12 +import com.lframework.xingyun.sc.mappers.HolidaysMapper;
  13 +import com.lframework.xingyun.sc.service.HolidaysService;
  14 +import org.apache.commons.collections4.CollectionUtils;
  15 +import org.apache.commons.lang3.BooleanUtils;
  16 +import org.apache.commons.lang3.StringUtils;
  17 +import org.springframework.cache.annotation.CacheEvict;
  18 +import org.springframework.stereotype.Service;
  19 +import org.springframework.transaction.annotation.Transactional;
  20 +
  21 +import java.io.BufferedReader;
  22 +import java.io.InputStreamReader;
  23 +import java.io.Serializable;
  24 +import java.net.HttpURLConnection;
  25 +import java.net.URL;
  26 +import java.nio.charset.StandardCharsets;
  27 +import java.time.LocalDate;
  28 +import java.util.ArrayList;
  29 +import java.util.Collections;
  30 +import java.util.List;
  31 +import java.util.stream.Collectors;
  32 +
  33 +@Service
  34 +public class HolidaysServiceImpl extends BaseMpServiceImpl<HolidaysMapper, Holidays> implements HolidaysService {
  35 +
  36 + @Override
  37 + public List<Holidays> query(Holidays vo) {
  38 + return getBaseMapper().query(vo);
  39 + }
  40 +
  41 + @Override
  42 + public Holidays findById(String id) {
  43 + return getBaseMapper().selectById(id);
  44 + }
  45 +
  46 + @Transactional(rollbackFor = Exception.class)
  47 + @Override
  48 + public String create(Holidays vo) {
  49 + vo.setId(IdUtil.getUUID());
  50 + getBaseMapper().insert(vo);
  51 +
  52 + return vo.getId();
  53 + }
  54 +
  55 + @Override
  56 + public boolean isWithinWorkdayLimit(LocalDate startDate, LocalDate endDate, int maxWorkdays) throws Exception {
  57 + int startYear = startDate.getYear();
  58 + int endYear = endDate.getYear();
  59 +
  60 + List<Holidays> holidaysList = new ArrayList<>(getHolidaysForYear(startYear));
  61 +
  62 + if (endYear != startYear) {
  63 + holidaysList.addAll(getHolidaysForYear(endYear));
  64 + }
  65 +
  66 + if (CollectionUtils.isEmpty(holidaysList)) {
  67 + throw new DefaultClientException("获取节假日信息出错!");
  68 + }
  69 +
  70 + // 节假日休息日期
  71 + List<LocalDate> restHolidaysList = holidaysList.stream()
  72 + .filter(Holidays::getRest)
  73 + .map(Holidays::getHolidayDate)
  74 + .collect(Collectors.toList());
  75 +
  76 + // 节假日调休日期
  77 + List<LocalDate> unRestHolidaysList = holidaysList.stream()
  78 + .filter(holidays -> BooleanUtils.isFalse(holidays.getRest()))
  79 + .map(Holidays::getHolidayDate)
  80 + .collect(Collectors.toList());
  81 +
  82 + int workingDays = 0;
  83 + LocalDate currentDate = startDate.plusDays(1); // 从签订日第二天开始计算
  84 +
  85 + while (!currentDate.isAfter(endDate)) {
  86 + if (restHolidaysList.contains(currentDate)) {
  87 + currentDate = currentDate.plusDays(1);
  88 + continue;
  89 + }
  90 +
  91 + // 调休或者小于 1=周一, 5=周五
  92 + if (unRestHolidaysList.contains(currentDate) || currentDate.getDayOfWeek().getValue() <= 5) {
  93 + workingDays++;
  94 + }
  95 +
  96 + currentDate = currentDate.plusDays(1);
  97 + }
  98 +
  99 + return workingDays <= maxWorkdays;
  100 + }
  101 +
  102 + private List<Holidays> getHolidaysForYear(int year) throws Exception {
  103 + Holidays query = new Holidays();
  104 + query.setYear(year);
  105 + List<Holidays> holidays = query(query);
  106 +
  107 + if (CollectionUtils.isEmpty(holidays)) {
  108 + holidays = callHolidayApi(year);
  109 + }
  110 +
  111 + return holidays != null ? holidays : Collections.emptyList();
  112 + }
  113 +
  114 + private List<Holidays> callHolidayApi(int year) throws Exception {
  115 + String API_URL = "https://publicapi.xiaoai.me/holiday/year?date=" + year;
  116 +
  117 + StringBuilder response = new StringBuilder();
  118 + HttpURLConnection connection = null;
  119 +
  120 + try {
  121 + URL url = new URL(API_URL);
  122 + connection = (HttpURLConnection) url.openConnection();
  123 + connection.setRequestMethod("GET");
  124 + connection.setConnectTimeout(5000);
  125 + connection.setReadTimeout(5000);
  126 +
  127 + int responseCode = connection.getResponseCode();
  128 + if (responseCode == HttpURLConnection.HTTP_OK) {
  129 + try (BufferedReader reader = new BufferedReader(
  130 + new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
  131 + String line;
  132 + while ((line = reader.readLine()) != null) {
  133 + response.append(line);
  134 + }
  135 + }
  136 + } else {
  137 + throw new RuntimeException("HTTP请求失败,响应码: " + responseCode);
  138 + }
  139 + } finally {
  140 + if (connection != null) {
  141 + connection.disconnect();
  142 + }
  143 + }
  144 +
  145 + if (StringUtils.isBlank(response)) {
  146 + return null;
  147 + }
  148 +
  149 + Object data = JsonUtil.parseObj(response).get("data");
  150 + if (ObjectUtil.isNull(data)) {
  151 + return null;
  152 + }
  153 +
  154 + JSONArray jsonArray = JsonUtil.parseArray(data);
  155 + if (jsonArray.isEmpty()) {
  156 + return null;
  157 + }
  158 +
  159 + List<Holidays> holidaysList = new ArrayList<>(jsonArray.size());
  160 + for (Object object : jsonArray) {
  161 + if (ObjectUtil.isNull(object)) {
  162 + continue;
  163 + }
  164 +
  165 + JSONObject jsonObject = JsonUtil.parseObj(object);
  166 + Holidays holidays = new Holidays();
  167 + holidays.setYear(year);
  168 + holidays.setHolidayName(jsonObject.getStr("holiday"));
  169 + holidays.setRest(jsonObject.getInt("rest") == 1);
  170 + holidays.setHolidayDate(DateUtil.toLocalDate(jsonObject.getDate("date")));
  171 + holidaysList.add(holidays);
  172 + }
  173 +
  174 + if (CollectionUtils.isNotEmpty(holidaysList)) {
  175 + holidaysList.forEach(this::create);
  176 + }
  177 +
  178 + return holidaysList;
  179 + }
  180 +
  181 + @CacheEvict(value = Holidays.CACHE_NAME, key = "@cacheVariables.tenantId() + #key")
  182 + @Override
  183 + public void cleanCacheByKey(Serializable key) {
  184 +
  185 + }
  186 +}
\ No newline at end of file
... ...
... ... @@ -20,9 +20,12 @@ import com.lframework.starter.web.core.utils.OpLogUtil;
20 20 import com.lframework.starter.web.core.utils.PageHelperUtil;
21 21 import com.lframework.starter.web.core.utils.PageResultUtil;
22 22 import com.lframework.starter.web.inner.components.oplog.OtherOpLogType;
  23 +import com.lframework.xingyun.sc.entity.ContractDistributorStandard;
23 24 import com.lframework.xingyun.sc.entity.SpecLockDelayApplication;
24 25 import com.lframework.xingyun.sc.enums.CustomerDevelopStatus;
25 26 import com.lframework.xingyun.sc.mappers.SpecLockDelayApplicationMapper;
  27 +import com.lframework.xingyun.sc.service.HolidaysService;
  28 +import com.lframework.xingyun.sc.service.contract.ContractDistributorStandardService;
26 29 import com.lframework.xingyun.sc.service.contract.SpecLockDelayApplicationService;
27 30 import com.lframework.xingyun.sc.vo.contract.createVo.CreateSpecLockDelayApplicationVo;
28 31 import com.lframework.xingyun.sc.vo.contract.queryVo.QuerySpecLockDelayApplicationVo;
... ... @@ -36,6 +39,7 @@ import org.springframework.stereotype.Service;
36 39 import org.springframework.transaction.annotation.Transactional;
37 40
38 41 import java.io.Serializable;
  42 +import java.time.LocalDate;
39 43 import java.time.LocalDateTime;
40 44 import java.util.List;
41 45 import java.util.stream.Collectors;
... ... @@ -49,6 +53,10 @@ public class SpecLockDelayApplicationServiceImpl extends BaseMpServiceImpl<SpecL
49 53 private FlowInstanceWrapperService flowInstanceWrapperService;
50 54 @Autowired
51 55 private FlowTaskWrapperMapper flowTaskWrapperMapper;
  56 + @Autowired
  57 + private ContractDistributorStandardService contractDistributorStandardService;
  58 + @Autowired
  59 + private HolidaysService holidaysService;
52 60
53 61 @Override
54 62 public PageResult<SpecLockDelayApplication> query(Integer pageIndex, Integer pageSize, QuerySpecLockDelayApplicationVo vo) {
... ... @@ -90,7 +98,8 @@ public class SpecLockDelayApplicationServiceImpl extends BaseMpServiceImpl<SpecL
90 98 @OpLog(type = OtherOpLogType.class, name = "新增锁价无规格操作申请单,ID:{}", params = {"#id"})
91 99 @Transactional(rollbackFor = Exception.class)
92 100 @Override
93   - public String create(CreateSpecLockDelayApplicationVo vo) {
  101 + public String create(CreateSpecLockDelayApplicationVo vo) throws Exception {
  102 + checkSpecLockDateLimit(vo.getApplicationCount(), vo.getContractId(), vo.getSpecLockDate());
94 103
95 104 SpecLockDelayApplication data = new SpecLockDelayApplication();
96 105 data.setId(IdUtil.getUUID());
... ... @@ -110,10 +119,29 @@ public class SpecLockDelayApplicationServiceImpl extends BaseMpServiceImpl<SpecL
110 119 return data.getId();
111 120 }
112 121
  122 + private void checkSpecLockDateLimit(Integer applicationCount, String contractId, LocalDate specLockDate) throws Exception {
  123 + if (applicationCount == 1) {
  124 + ContractDistributorStandard contractDistributorStandard = contractDistributorStandardService.findById(contractId);
  125 + if (!holidaysService.isWithinWorkdayLimit(contractDistributorStandard.getOrderDate(), specLockDate, 10)) {
  126 + throw new DefaultClientException("第一次申请的延期时间不能超过正式合同签订时间之日起的10个工作日!");
  127 + }
  128 + } else {
  129 + // 获取上一次的申请数据
  130 + Wrapper<SpecLockDelayApplication> wrapper = Wrappers.lambdaQuery(SpecLockDelayApplication.class)
  131 + .eq(SpecLockDelayApplication::getContractId, contractId)
  132 + .eq(SpecLockDelayApplication::getApplicationCount, applicationCount - 1);
  133 + SpecLockDelayApplication lastApplication = getBaseMapper().selectOne(wrapper);
  134 + if (!holidaysService.isWithinWorkdayLimit(lastApplication.getSpecLockDate(), specLockDate, 5)) {
  135 + throw new DefaultClientException("申请的延期时间与上一次申请延期时间不能超过5个工作日!");
  136 + }
  137 + }
  138 + }
  139 +
113 140 @OpLog(type = OtherOpLogType.class, name = "修改锁价无规格操作申请单,ID:{}", params = {"#id"})
114 141 @Transactional(rollbackFor = Exception.class)
115 142 @Override
116   - public void update(UpdateSpecLockDelayApplicationVo vo) {
  143 + public void update(UpdateSpecLockDelayApplicationVo vo) throws Exception {
  144 + checkSpecLockDateLimit(vo.getApplicationCount(), vo.getContractId(), vo.getSpecLockDate());
117 145
118 146 SpecLockDelayApplication data = getBaseMapper().selectById(vo.getId());
119 147 if (ObjectUtil.isNull(data)) {
... ...
  1 +package com.lframework.xingyun.sc.mappers;
  2 +
  3 +import com.lframework.starter.web.core.mapper.BaseMapper;
  4 +import com.lframework.xingyun.sc.entity.Holidays;
  5 +import org.apache.ibatis.annotations.Param;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * <p>
  11 + * 节假日 Mapper 接口
  12 + * </p>
  13 + */
  14 +public interface HolidaysMapper extends BaseMapper<Holidays> {
  15 +
  16 + /**
  17 + * 查询列表
  18 + *
  19 + * @param vo
  20 + * @return
  21 + */
  22 + List<Holidays> query(@Param("vo") Holidays vo);
  23 +}
... ...
  1 +package com.lframework.xingyun.sc.service;
  2 +
  3 +import com.lframework.starter.web.core.service.BaseMpService;
  4 +import com.lframework.xingyun.sc.entity.Holidays;
  5 +
  6 +import java.time.LocalDate;
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * 节假日 Service
  11 + */
  12 +public interface HolidaysService extends BaseMpService<Holidays> {
  13 +
  14 + /**
  15 + * 查询列表
  16 + *
  17 + * @param vo
  18 + * @return
  19 + */
  20 + List<Holidays> query(Holidays vo);
  21 +
  22 + /**
  23 + * 根据ID查询
  24 + *
  25 + * @param id
  26 + * @return
  27 + */
  28 + Holidays findById(String id);
  29 +
  30 + /**
  31 + * 创建
  32 + *
  33 + * @param vo
  34 + * @return
  35 + */
  36 + String create(Holidays vo);
  37 +
  38 + /**
  39 + * 计算是否超过指定工作日日期
  40 + *
  41 + * @param startDate 开始日期
  42 + * @param endDate 结束日期
  43 + * @param maxWorkdays 最大工作日
  44 + * @return true表示没有超过,false表示超过了
  45 + */
  46 + boolean isWithinWorkdayLimit(LocalDate startDate, LocalDate endDate, int maxWorkdays) throws Exception;
  47 +}
... ...
... ... @@ -43,14 +43,14 @@ public interface SpecLockDelayApplicationService extends BaseMpService<SpecLockD
43 43 * @param vo
44 44 * @return
45 45 */
46   - String create(CreateSpecLockDelayApplicationVo vo);
  46 + String create(CreateSpecLockDelayApplicationVo vo) throws Exception;
47 47
48 48 /**
49 49 * 修改
50 50 *
51 51 * @param vo
52 52 */
53   - void update(UpdateSpecLockDelayApplicationVo vo);
  53 + void update(UpdateSpecLockDelayApplicationVo vo) throws Exception;
54 54
55 55 /**
56 56 * 更新审核状态
... ...
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="com.lframework.xingyun.sc.mappers.HolidaysMapper">
  4 +
  5 + <resultMap id="Holidays" type="com.lframework.xingyun.sc.entity.Holidays">
  6 + <id column="id" property="id"/>
  7 + <result column="year" property="year"/>
  8 + <result column="holiday_date" property="holidayDate"/>
  9 + <result column="rest" property="rest"/>
  10 + <result column="holiday_name" property="holidayName"/>
  11 + <result column="create_by_id" property="createById"/>
  12 + <result column="create_by" property="createBy"/>
  13 + <result column="update_by_id" property="updateById"/>
  14 + <result column="update_by" property="updateBy"/>
  15 + <result column="create_time" property="createTime"/>
  16 + <result column="update_time" property="updateTime"/>
  17 + </resultMap>
  18 +
  19 + <sql id="Holidays_sql">
  20 + SELECT tb.id,
  21 + tb.year,
  22 + tb.holiday_date,
  23 + tb.rest,
  24 + tb.holiday_name,
  25 + tb.create_by_id,
  26 + tb.create_by,
  27 + tb.update_by_id,
  28 + tb.update_by,
  29 + tb.create_time,
  30 + tb.update_time
  31 + FROM tbl_holidays AS tb
  32 + </sql>
  33 +
  34 + <select id="query" resultMap="Holidays">
  35 + <include refid="Holidays_sql"/>
  36 + <where>
  37 + <if test="vo.year != null">
  38 + AND tb.year = #{vo.year}
  39 + </if>
  40 + <if test="vo.holidayDate != null">
  41 + AND tb.holiday_date = #{vo.holidayDate}
  42 + </if>
  43 + </where>
  44 + order by tb.year,tb.holiday_date
  45 + </select>
  46 +</mapper>
... ...