From c96fbe6b0aeb413a17c429133ee6d81d138144b9 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期二, 09 六月 2026 10:58:52 +0800
Subject: [PATCH] Merge branch '1.0' of http://120.76.84.145:10101/gitblit/r/java/Robotaxi into 1.0

---
 xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpElectronicFenceManagementController.java |  441 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 418 insertions(+), 23 deletions(-)

diff --git a/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpElectronicFenceManagementController.java b/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpElectronicFenceManagementController.java
index 2b0785a..62cd452 100644
--- a/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpElectronicFenceManagementController.java
+++ b/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpElectronicFenceManagementController.java
@@ -1,28 +1,62 @@
 package com.xiaopeng.map.controller;
 
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.xiaopeng.api.dto.operation.ElectronicFenceAddDto;
 import com.xiaopeng.api.dto.operation.ElectronicFenceAreaUpdateStatusDto;
+import com.xiaopeng.api.dto.operation.ElectronicFenceOperationStrategyValidateDto;
 import com.xiaopeng.api.dto.operation.ElectronicFenceUpdateDto;
-import com.xiaopeng.api.feignClient.operation.XpElectronicClient;
-import com.xiaopeng.api.model.operation.XpElectronicFence;
-import com.xiaopeng.api.model.operation.XpElectronicFenceArea;
-import com.xiaopeng.api.model.operation.XpPoint;
+import com.xiaopeng.api.model.operation.*;
 import com.xiaopeng.api.query.operation.ElectronicPageListQuery;
+import com.xiaopeng.api.query.operation.PointListQuery;
+import com.xiaopeng.api.query.operation.XpStationQuery;
 import com.xiaopeng.api.vo.operation.ElectronicFenceDetailVo;
 import com.xiaopeng.common.core.domain.R;
 import com.xiaopeng.common.core.exception.ServiceException;
 import com.xiaopeng.common.core.utils.bean.BeanUtils;
 import com.xiaopeng.common.core.web.page.PageInfo;
+import com.xiaopeng.common.log.annotation.AdminOperationLog;
+import com.xiaopeng.common.log.enums.AdminBusinessType;
+import com.xiaopeng.common.log.enums.AdminOperationType;
+import com.xiaopeng.map.constant.I18nKeyConstant;
+import com.xiaopeng.map.service.*;
+import com.xiaopeng.map.service.serviceimpl.BootCommonService;
+import com.xiaopeng.map.utils.OperationStrategyIndex;
+import com.xiaopeng.api.query.operation.FenceAndStationVo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
+import org.apache.shardingsphere.transaction.core.TransactionType;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.xiaopeng.map.service.serviceimpl.XpElectronicFenceServiceImpl.getPinyinInitials;
+import com.xiaopeng.common.log.annotation.AdminOperationLog;
+import com.xiaopeng.common.log.enums.AdminBusinessType;
+import com.xiaopeng.common.log.enums.AdminOperationType;
 
 /**
  * <p>
@@ -39,24 +73,77 @@
 public class XpElectronicFenceManagementController {
 
 
+    @Resource
+    private XpElectronicFenceService xpElectronicFenceService;
 
     @Resource
-    private XpElectronicClient xpElectronicClient;
+    private XpElectronicFenceAreaService xpElectronicFenceAreaService;
 
-    @ApiOperation(value = "电子围栏管理列表", response = XpPoint.class)
-    @PostMapping("/pageList")
-    public R<PageInfo<XpElectronicFence>> pageList(@RequestBody ElectronicPageListQuery query) {
-        return R.ok(xpElectronicClient.pageList(query).getData());
+    @Resource
+    private XpRegionService regionService;
+    @Autowired
+    private XpRegionService xpRegionService;
+
+    @Autowired
+    private XpPointService xpPointService;
+    @Resource
+    private XpStationService xpStationService;
+    @Resource
+    private BootCommonService bootCommonService;
+
+    /**
+     * 查询省市管理
+     */
+    @ApiOperation(value = "查询省市区",response = XpRegion.class)
+    @GetMapping(value = "/getRegion")
+    public R<List<List<XpRegion>>> geXpRegion() {
+        return R.ok(regionService.getXpRegion());
     }
 
+    @ApiOperation(value = "获取围栏和场站数据",tags = {"管理后台-电子围栏"})
+    @GetMapping(value = "/findListFenceAndStation")
+    public R<List<FenceAndStationVo>> findListFenceAndStation(String cityCode) {
+        return R.ok(xpPointService.findListFenceAndStation(cityCode));
+    }
+
+    @ApiOperation(value = "获取不分页的电子围栏列表",tags = {"管理后台-电子围栏"})
+    @PostMapping("/list")
+    R<List<XpElectronicFence>> getList(@RequestBody ElectronicPageListQuery query){
+        return R.ok(xpElectronicFenceService.getList(query));
+    }
+
+
+    @ApiOperation(value = "电子围栏管理列表", response = XpElectronicFence.class)
+    @PostMapping("/pageList")
+    public R<PageInfo<XpElectronicFence>> pageList(@RequestBody ElectronicPageListQuery query) {
+        PageInfo<XpElectronicFence> pageList = xpElectronicFenceService.pageList(query);
+        return R.ok(pageList);
+    }
+    /**
+     * 电子围栏列表接口
+     *
+     * @return 电子围栏列表
+     */
+    @ApiOperation(value = "电子围栏列表接口", tags = {"运维APP-电子围栏"})
+    @GetMapping("/maintenance-app/api/v1/electronicFence/list")
+    public R<List<XpElectronicFence>> vehicleMap() {
+        List<XpElectronicFence> list = xpElectronicFenceService.list();
+        return R.ok(list);
+    }
     /**
      * 新增电子围栏
      */
     @PostMapping("/add")
     @ApiOperation(value = "新增电子围栏")
-    @Transactional
+    @AdminOperationLog(
+            businessType = AdminBusinessType.ELECTRONIC_FENCE_MANAGEMENT,
+            operationType = AdminOperationType.ADD,
+            content = "新增电子围栏",
+            appendRequestData = true
+    )
     public R add(@Validated @RequestBody ElectronicFenceAddDto dto) {
-        return xpElectronicClient.add(dto);
+        validateFenceTime(dto.getStatus(), dto.getEffectType(), dto.getEffectTime(), dto.getFailureType(), dto.getFailureTime());
+        return xpElectronicFenceService.addElectronic(dto);
     }
 
 
@@ -67,40 +154,348 @@
     @PostMapping("/updateStatus")
     @ResponseBody
     @ApiOperation(value = "修改状态")
+    @AdminOperationLog(
+            businessType = AdminBusinessType.ELECTRONIC_FENCE_MANAGEMENT,
+            operationType = AdminOperationType.EDIT,
+            content = "修改电子围栏状态",
+            appendRequestData = true
+    )
     public R updateStatus(@RequestBody ElectronicFenceAreaUpdateStatusDto dto) {
-
-        return xpElectronicClient.updateStatus(dto);
+        XpElectronicFenceArea electronicFenceArea = xpElectronicFenceAreaService.getById(dto.getId());
+        if (electronicFenceArea == null) {
+            throw new ServiceException(
+                    "围栏构成不存在,请刷新重试",
+                    I18nKeyConstant.FENCE_STRUCTURE_NOT_EXIST
+            );
+        }
+        xpElectronicFenceAreaService.updateById(electronicFenceArea);
+        return R.ok();
     }
 
     /**
      * 电子围栏详情
      */
-    @GetMapping("/queryById")
-    @ResponseBody
+    @PostMapping("/queryById")
     @ApiOperation(value = "电子围栏详情")
-    public R<ElectronicFenceDetailVo> queryById(Long id) {
-        return xpElectronicClient.queryById(id);
+    public R<ElectronicFenceDetailVo> queryById(@RequestParam("id")Long id) {
+        ElectronicFenceDetailVo res = new ElectronicFenceDetailVo();
+        XpElectronicFence electronicFence = xpElectronicFenceService.getById(id);
+        if (electronicFence == null) {
+            throw new ServiceException(
+                    "电子围栏不存在,请刷新重试",
+                    I18nKeyConstant.FENCE_NOT_EXIST
+            );
+        }
+        BeanUtils.copyProperties(electronicFence, res);
+        List<XpElectronicFenceArea> electronicFenceAreaList = xpElectronicFenceAreaService.lambdaQuery().eq(XpElectronicFenceArea::getElectronicId, id)
+                .list();
+        res.setElectronicFenceAreas(electronicFenceAreaList);
+
+        //点位的总数
+        if(!electronicFenceAreaList.isEmpty()){
+            PointListQuery query1 = new PointListQuery();
+            query1.setElectronicAreaIds(electronicFenceAreaList.stream().map(XpElectronicFenceArea::getId).collect(Collectors.toList()));
+            List<XpPoint> pointList = xpPointService.findList(query1);
+
+            ElectronicFenceDetailVo.Numbers pointsNumbers = new ElectronicFenceDetailVo.Numbers();
+            if(CollUtil.isNotEmpty(pointList)){
+                LocalTime localTime = LocalTime.now();
+                //总数
+                pointsNumbers.setTotalNum(pointList.size());
+                //待测试
+                long count = pointList.stream().filter(xpPoint -> xpPoint.getOperationStatus() == 1 && xpPoint.getVerificationStatus() == 1).count();
+                pointsNumbers.setToBeTested(Integer.parseInt(count+""));
+                //测试中
+                long count2 = pointList.stream().filter(xpPoint -> xpPoint.getOperationStatus() == 1 && xpPoint.getVerificationStatus() == 2).count();
+                pointsNumbers.setTesting(Integer.parseInt(count2+""));
+                //测试不通过
+                long count3 = pointList.stream().filter(xpPoint -> xpPoint.getOperationStatus() == 1 && xpPoint.getVerificationStatus() == 4).count();
+                pointsNumbers.setTestNotPass(Integer.parseInt(count3+""));
+                //待启用
+                long count4 = pointList.stream().filter(xpPoint -> xpPoint.getOperationStatus() == 1 && (xpPoint.getVerificationStatus() == 3 || xpPoint.getVerificationStatus() == 5)).count();
+                pointsNumbers.setPendingLaunch(Integer.parseInt(count4+""));
+                //启用中
+                long count5 = pointList.stream().filter(xpPoint -> xpPoint.getOperationStatus() == 2 && xpPoint.getVerificationStatus() == 5).count();
+                pointsNumbers.setStartingUp(Integer.parseInt(count5+""));
+                //已停用
+                long count6 = pointList.stream().filter(xpPoint -> xpPoint.getOperationStatus() == 3 && xpPoint.getVerificationStatus() == 5).count();
+                pointsNumbers.setDisabled(Integer.parseInt(count6+""));
+                //已失效
+                long count7 = pointList.stream().filter(xpPoint -> xpPoint.getOperationStatus() == 4 && xpPoint.getVerificationStatus() == 5).count();
+                pointsNumbers.setExpired(Integer.parseInt(count7+""));
+            }
+            res.setPointsNumbers(pointsNumbers);
+        }
+
+        //场站总数
+        XpStationQuery query2 = new XpStationQuery();
+        query2.setElectronicId(id);
+        List<XpStation> stationList = xpStationService.findList(query2);
+
+        ElectronicFenceDetailVo.Numbers stationNumbers = new ElectronicFenceDetailVo.Numbers();
+        if(CollUtil.isNotEmpty(stationList)){
+            //status 场站状态 0=草稿 1=待启用 2=启用中 3=已停用 4=失效
+            stationNumbers.setTotalNum(stationList.size());
+            //待生效
+            long count1 = stationList.stream().filter(xpStation -> xpStation.getStatus() == 1).count();
+            stationNumbers.setPendingLaunch(Integer.parseInt(count1+""));
+            //启用中
+            long count2 = stationList.stream().filter(xpStation -> xpStation.getStatus() == 2).count();
+            stationNumbers.setStartingUp(Integer.parseInt(count2+""));
+            //已停用
+            long count3 = stationList.stream().filter(xpStation -> xpStation.getStatus() == 3).count();
+            stationNumbers.setDisabled(Integer.parseInt(count3+""));
+            //已失效
+            long count4 = stationList.stream().filter(xpStation -> xpStation.getStatus() == 4).count();
+            stationNumbers.setExpired(Integer.parseInt(count4+""));
+        }
+        res.setStationNumbers(stationNumbers);
+        return R.ok(res);
     }
 
     /**
      * 编辑电子围栏
      */
     @PostMapping("/edit")
-    @ResponseBody
     @ApiOperation(value = "编辑电子围栏")
     @Transactional
+    @ShardingSphereTransactionType(TransactionType.BASE)
+    @AdminOperationLog(
+            businessType = AdminBusinessType.ELECTRONIC_FENCE_MANAGEMENT,
+            operationType = AdminOperationType.EDIT,
+            content = "编辑电子围栏",
+            appendRequestData = true
+    )
     public R edit(@Validated @RequestBody ElectronicFenceUpdateDto dto) {
-        return xpElectronicClient.edit(dto);
+        validateFenceTime(dto.getStatus(), dto.getEffectType(), dto.getEffectTime(), dto.getFailureType(), dto.getFailureTime());
+        return xpElectronicFenceService.editElectronic(dto);
+    }
+
+    /**
+     * 校验编辑围栏时运营时间段缩短影响的点位数量
+     * <p>
+     * 统计:围栏下 operation_type=2(自定义运营时间段) 的点位中,
+     * 当围栏运营时间范围发生缩短时,不在新运营时间范围(Union)内的点位数量(需要停用)。
+     * </p>
+     */
+    @PostMapping("/validateOperationStrategyShorten")
+    @ApiOperation(value = "校验围栏运营时间段缩短影响点位数量")
+    public R<Integer> validateOperationStrategyShorten(@Valid @RequestBody ElectronicFenceOperationStrategyValidateDto dto) {
+        XpElectronicFence fence = xpElectronicFenceService.getById(dto.getId());
+        if (fence == null) {
+            throw new ServiceException("围栏不存在", I18nKeyConstant.FENCE_NOT_EXIST);
+        }
+
+        OperationStrategyIndex oldIndex = OperationStrategyIndex.parse(fence.getOperationStrategy());
+        OperationStrategyIndex newIndex = OperationStrategyIndex.parse(dto.getOperationStrategy());
+        if (oldIndex.equalsNormalized(newIndex)) {
+            return R.ok(0);
+        }
+        if (!oldIndex.hasAnyShrinkComparedTo(newIndex)) {
+            return R.ok(0);
+        }
+
+        List<Long> fenceAreaIds = xpElectronicFenceAreaService.lambdaQuery()
+                .eq(XpElectronicFenceArea::getElectronicId, dto.getId())
+                .list()
+                .stream()
+                .map(XpElectronicFenceArea::getId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        if (CollUtil.isEmpty(fenceAreaIds)) {
+            return R.ok(0);
+        }
+
+        List<XpPoint> customPoints = xpPointService.lambdaQuery()
+                .in(XpPoint::getElectronicAreaId, fenceAreaIds)
+                .eq(XpPoint::getPointType, 1)
+                .eq(XpPoint::getOperationType, 2)
+                .list();
+        if (CollUtil.isEmpty(customPoints)) {
+            return R.ok(0);
+        }
+
+        int disableCount = 0;
+        for (XpPoint point : customPoints) {
+            if (point == null || point.getEffectiveTimePeriod() == null || point.getEffectiveTimePeriod().isEmpty()) {
+                continue;
+            }
+            List<OperationStrategyIndex.TimeInterval> pointIntervals = OperationStrategyIndex.parsePointEffectiveTimePeriod(point.getEffectiveTimePeriod());
+            if (pointIntervals.isEmpty()) {
+                continue;
+            }
+
+            boolean shouldDisable = !newIndex.isPointScheduleWithin(pointIntervals);
+            if (shouldDisable) {
+                disableCount++;
+            }
+        }
+
+        List<XpStation> listByElectronicId = xpStationService.findListByElectronicId(dto.getId());
+        if(CollUtil.isNotEmpty(listByElectronicId)){
+
+            for (XpStation bean : listByElectronicId) {
+                if (StrUtil.isBlank(bean.getEffectiveTimePeriod())) {
+                    continue;
+                }
+                List<OperationStrategyIndex.TimeInterval> pointIntervals = OperationStrategyIndex.parsePointEffectiveTimePeriod(bean.getEffectiveTimePeriod());
+                if (pointIntervals.isEmpty()) {
+                    continue;
+                }
+
+                boolean shouldDisable = !newIndex.isPointScheduleWithin(pointIntervals);
+                if (shouldDisable) {
+                    disableCount++;
+                }
+            }
+        }
+        return R.ok(disableCount);
     }
 
     /**
      * 复制电子围栏
      */
-    @GetMapping("/copy")
-    @ResponseBody
+    @PostMapping("/copy")
     @ApiOperation(value = "复制电子围栏")
     @Transactional
-    public R copy(Integer id) {
-        return xpElectronicClient.copy(id);
+    @ShardingSphereTransactionType(TransactionType.BASE)
+    @AdminOperationLog(
+            businessType = AdminBusinessType.ELECTRONIC_FENCE_MANAGEMENT,
+            operationType = AdminOperationType.ADD,
+            contentExpression = "'复制电子围栏,id=' + #p0",
+            appendRequestData = false
+    )
+    public R<Long> copy(@RequestParam("id") Integer id) {
+        XpElectronicFence electronicFence = xpElectronicFenceService.getById(id);
+        if (electronicFence.getStatus()==2){
+            throw new ServiceException(
+                    "当前电子围栏状态为启用中,不可复制",
+                    I18nKeyConstant.FENCE_STATUS_CANNOT_COPIED
+            );
+        }
+        electronicFence.setElectronicName(buildCopyFenceName(electronicFence.getElectronicName()));
+        electronicFence.setId(null);
+        electronicFence.setStatus(0);
+        List<XpElectronicFenceArea> electronicFenceAreaList = xpElectronicFenceAreaService.lambdaQuery().eq(XpElectronicFenceArea::getElectronicId, id)
+                .list();
+        //根据经纬度获取当前城市code
+        // 生成围栏id 规则:城市首字母-类型简写-4位自增流水号(如 SZ-OP-001),支持复制;数据停用或删除后,流水号不回收
+        XpRegion xpRegion = xpRegionService.getOne(new LambdaQueryWrapper<XpRegion>()
+                .eq(XpRegion::getCode, electronicFence.getCityCode()));
+        String name = xpRegion.getName();
+        // 根据城市中文名,截取前两位的首字母并且大写
+        // 截取前两个字符
+        String prefix = name.substring(0, 2);
+        // 获取拼音首字母并大写
+        String result = getPinyinInitials(prefix).toUpperCase();
+        xpElectronicFenceService.save(electronicFence);
+        electronicFence.setElectronicNumber(result + "-OP-" + String.format("%04d", electronicFence.getId()));
+        xpElectronicFenceService.updateById(electronicFence);
+        for (XpElectronicFenceArea area : electronicFenceAreaList) {
+            area.setId(null);
+            area.setElectronicId(electronicFence.getId());
+            area.setAreaStatus(2);
+            area.setAreaName("副本_"+area.getAreaName());
+        }
+        xpElectronicFenceAreaService.saveBatch(electronicFenceAreaList);
+        return R.ok(electronicFence.getId());
+    }
+
+    private String buildCopyFenceName(String sourceName) {
+        Set<String> existingNames = new HashSet<>(xpElectronicFenceService.lambdaQuery()
+                .likeRight(XpElectronicFence::getElectronicName, sourceName)
+                .list()
+                .stream()
+                .map(XpElectronicFence::getElectronicName)
+                .collect(Collectors.toSet()));
+
+        String candidateName = sourceName + "_副本";
+        while (existingNames.contains(candidateName)) {
+            candidateName = candidateName + "_副本";
+        }
+        return candidateName;
+    }
+
+    /**
+     * 根据ID列表批量查询电子围栏
+     *
+     * @param electronicIdSet
+     * @return
+     */
+    @PostMapping("/listByIds")
+    R<List<XpElectronicFence>> listByIds(@RequestBody Collection<Long> electronicIdSet) {
+        if (CollUtil.isEmpty(electronicIdSet)) {
+            return R.ok(Collections.emptyList());
+        }
+        return R.ok(xpElectronicFenceService.listByIds(electronicIdSet));
+    }
+
+    @ApiOperation(value = "获取已启用的电子围栏列表",tags = {"管理后台-电子围栏"})
+    @GetMapping("/available/list")
+    R<List<XpElectronicFence>> getAvailableList(){
+        return R.ok(xpElectronicFenceService.getAvailableList());
+    }
+
+
+
+
+    /**
+     * 批量查询电子围栏
+     * @param fenceIds
+     * @return
+     */
+    @PostMapping("/inner/xpElectronicFence/selectBatchIds")
+    public R<List<XpElectronicFence>> selectBatchIds(@RequestBody List<String> fenceIds){
+        List<XpElectronicFence> xpElectronicFences = xpElectronicFenceService.listByIds(fenceIds);
+        return R.ok(xpElectronicFences);
+    }
+
+
+    /**
+     * 根据ID查询电子围栏
+     * @param fenceId
+     * @return
+     */
+    @GetMapping("/inner/xpElectronicFence/selectById")
+    public R<XpElectronicFence> selectById(@RequestParam String fenceId){
+        XpElectronicFence xpElectronicFence = xpElectronicFenceService.getById(fenceId);
+        return R.ok(xpElectronicFence);
+    }
+
+    /**
+     * 校验围栏生效时间和失效时间的合法性:
+     * <ul>
+     *   <li>生效类型不是立即生效(effectType != 1)时,生效时间不能早于当前时间</li>
+     *   <li>失效类型不是永不失效(failureType != 1)时,失效时间不能早于当前时间</li>
+     * </ul>
+     *
+     * @param status
+     * @param effectType  生效类型(1=立即生效 2=定时生效)
+     * @param effectTime  生效时间
+     * @param failureType 失效类型(1=永不失效 2=定时失效)
+     * @param failureTime 失效时间
+     */
+    private void validateFenceTime(@NotNull Integer status, Integer effectType, LocalDateTime effectTime,
+                                   Integer failureType, LocalDateTime failureTime) {
+        LocalDateTime now = LocalDateTime.now();
+        // 发布/启用时,定时生效的生效时间不能早于当前时间
+        if (requiresScheduleValidation(status) && effectType != null && effectType != 1) {
+            if (effectTime == null || effectTime.isBefore(now)) {
+                throw new ServiceException("围栏生效时间不合法,定时生效时生效时间不能早于当前时间",
+                        I18nKeyConstant.FENCE_EFFECT_TIME_INVALID);
+            }
+        }
+        // 发布/启用时,定时失效的失效时间不能早于当前时间
+        if (requiresScheduleValidation(status) && failureType != null && failureType != 1) {
+            if (failureTime == null || failureTime.isBefore(now)) {
+                throw new ServiceException("围栏失效时间不合法,定时失效时失效时间不能早于当前时间",
+                        I18nKeyConstant.FENCE_FAILURE_TIME_INVALID);
+            }
+        }
+    }
+
+    private boolean requiresScheduleValidation(Integer status) {
+        return status != null && (status == 1 || status == 2);
     }
 }

--
Gitblit v1.7.1