Ver código fonte

开发新增免车费规则接口

jinshihui 7 horas atrás
pai
commit
eda79572f4

+ 81 - 1
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TFareSettingController.java

@@ -1,15 +1,19 @@
 package com.ylx.web.controller.massage;
 
 
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ylx.common.core.controller.BaseController;
 import com.ylx.common.core.domain.R;
 import com.ylx.massage.domain.TFareSetting;
+import com.ylx.massage.domain.TFareFreeRule;
+import com.ylx.massage.domain.vo.FareFreeRuleVo;
+import com.ylx.massage.service.TFareSettingService;
+import com.ylx.massage.service.TFareFreeRuleService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.web.bind.annotation.*;
-import com.ylx.massage.service.TFareSettingService;
 import javax.annotation.Resource;
 import java.io.Serializable;
 import java.util.List;
@@ -30,6 +34,12 @@ public class TFareSettingController extends BaseController {
     @Resource
     private TFareSettingService tFareSettingService;
 
+    /**
+     * 免车费规则服务
+     */
+    @Resource
+    private TFareFreeRuleService fareFreeRuleService;
+
     /**
      * 分页查询所有车费设置数据
      *
@@ -89,5 +99,75 @@ public class TFareSettingController extends BaseController {
     public R delete(@RequestBody List<String> idList) {
         return R.ok(this.tFareSettingService.removeByIds(idList));
     }
+
+    /**
+     * 新增免车费规则
+     *
+     * @param fareFreeRule 免车费规则
+     * @return R
+     */
+    @PostMapping("fareFreeRule/add")
+    @ApiOperation("新增免车费规则")
+    public R addFareFreeRule(@RequestBody TFareFreeRule fareFreeRule) {
+        try {
+            logger.info("新增免车费规则:,前端传递的参数:{}", JSON.toJSONString(fareFreeRule));
+            boolean success = fareFreeRuleService.addFareFreeRule(fareFreeRule);
+            return success ? R.ok("新增成功") : R.fail("新增失败");
+        } catch (Exception e) {
+            return R.fail(e.getMessage());
+        }
+    }
+
+    /**
+     * 修改免车费规则
+     *
+     * @param fareFreeRule 免车费规则
+     * @return R
+     */
+    @PostMapping("fareFreeRule/update")
+    @ApiOperation("修改免车费规则")
+    public R updateFareFreeRule(@RequestBody TFareFreeRule fareFreeRule) {
+        try {
+            boolean success = fareFreeRuleService.updateFareFreeRule(fareFreeRule);
+            return success ? R.ok("修改成功") : R.fail("修改失败");
+        } catch (Exception e) {
+            return R.fail(e.getMessage());
+        }
+    }
+
+    /**
+     * 查询免车费规则列表
+     *
+     * @return R
+     */
+    @GetMapping("fareFreeRule/list")
+    @ApiOperation("查询免车费规则列表")
+    public R listFareFreeRules() {
+        try {
+            Long deptIdLong = com.ylx.common.utils.SecurityUtils.getDeptId();
+            String deptId = String.valueOf(deptIdLong);
+            List<FareFreeRuleVo> list = fareFreeRuleService.listFareFreeRules(deptId);
+            return R.ok(list);
+        } catch (Exception e) {
+            return R.fail(e.getMessage());
+        }
+    }
+
+    /**
+     * 删除免车费规则
+     *
+     * @param idList 规则ID列表
+     * @return R
+     */
+    @PostMapping("fareFreeRule/delete")
+    @ApiOperation("删除免车费规则")
+    public R deleteFareFreeRule(@RequestBody List<String> idList) {
+        try {
+            boolean success = fareFreeRuleService.removeByIds(idList);
+            return success ? R.ok("删除成功") : R.fail("删除失败");
+        } catch (Exception e) {
+            return R.fail(e.getMessage());
+        }
+    }
 }
 

+ 120 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/TFareFreeRule.java

@@ -0,0 +1,120 @@
+package com.ylx.massage.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 免车费规则表
+ *
+ * @author system
+ * @since 2024-01-13
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName(value = "t_fare_free_rule", autoResultMap = true)
+@ApiModel(value = "TFareFreeRule", description = "免车费规则")
+public class TFareFreeRule implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @ApiModelProperty("主键ID")
+    private String id;
+
+    /**
+     * 技师ID
+     */
+    @ApiModelProperty("技师ID")
+    @TableField(value = "tech_id")
+    private String techId;
+
+    /**
+     * 服务项目ID
+     */
+    @TableField(value = "project_id")
+    @ApiModelProperty("服务项目ID")
+    private String projectId;
+
+    /**
+     * 服务时间段列表
+     * 格式:[{"startTime":"08:00","endTime":"12:00"},{"startTime":"14:00","endTime":"18:00"}]
+     */
+    @TableField(value = "time_ranges", typeHandler = FastjsonTypeHandler.class)
+    @ApiModelProperty("服务时间段列表")
+    private List<TimeRange> timeRanges;
+
+    /**
+     * 最小距离(公里)
+     * 订单距离 <= 此值时免车费
+     */
+    @ApiModelProperty("最小距离(公里)")
+    private Integer minDistance;
+
+    /**
+     * 是否启用(0否 1是)
+     */
+    @ApiModelProperty("是否启用(0否 1是)")
+    private Integer enable;
+
+
+    /**
+     * 创建时间
+     */
+    @ApiModelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    @ApiModelProperty("更新时间")
+    private LocalDateTime updateTime;
+
+    /**
+     * 逻辑删除(0否 1是)
+     */
+    @TableLogic
+    @ApiModelProperty("逻辑删除(0否 1是)")
+    private Integer isDelete;
+
+    /**
+     * 时间段内部类
+     */
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @Builder
+    public static class TimeRange implements Serializable {
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 开始时间(格式:HH:mm)
+         */
+        @ApiModelProperty("开始时间")
+        private String startTime;
+
+        /**
+         * 结束时间(格式:HH:mm)
+         */
+        @ApiModelProperty("结束时间")
+        private String endTime;
+    }
+}

+ 75 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/FareFreeRuleVo.java

@@ -0,0 +1,75 @@
+package com.ylx.massage.domain.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 免车费规则VO
+ *
+ * @author system
+ * @since 2024-01-13
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel(value = "FareFreeRuleVo", description = "免车费规则VO")
+public class FareFreeRuleVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @ApiModelProperty("主键ID")
+    private String id;
+
+    /**
+     * 服务项目ID列表
+     */
+    @ApiModelProperty("服务项目ID列表")
+    private List<String> projectIds;
+
+    /**
+     * 服务项目名称列表(用于前端展示)
+     */
+    @ApiModelProperty("服务项目名称列表")
+    private String projectNames;
+
+    /**
+     * 服务时间段列表
+     */
+    @ApiModelProperty("服务时间段列表")
+    private List<TimeRangeVo> timeRanges;
+
+    /**
+     * 最小距离(公里)
+     */
+    @ApiModelProperty("最小距离(公里)")
+    private Integer minDistance;
+
+    /**
+     * 是否启用(0否 1是)
+     */
+    @ApiModelProperty("是否启用(0否 1是)")
+    private Integer enable;
+
+    /**
+     * 部门ID
+     */
+    @ApiModelProperty("部门ID")
+    private String deptId;
+
+    /**
+     * 部门名称
+     */
+    @ApiModelProperty("部门名称")
+    private String deptName;
+}

+ 38 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/TimeRangeVo.java

@@ -0,0 +1,38 @@
+package com.ylx.massage.domain.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 时间段VO
+ *
+ * @author system
+ * @since 2024-01-13
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel(value = "TimeRangeVo", description = "时间段VO")
+public class TimeRangeVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 开始时间(格式:HH:mm)
+     */
+    @ApiModelProperty("开始时间")
+    private String startTime;
+
+    /**
+     * 结束时间(格式:HH:mm)
+     */
+    @ApiModelProperty("结束时间")
+    private String endTime;
+}

+ 15 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/mapper/TFareFreeRuleMapper.java

@@ -0,0 +1,15 @@
+package com.ylx.massage.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ylx.massage.domain.TFareFreeRule;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 免车费规则Mapper接口
+ *
+ * @author system
+ * @since 2024-01-13
+ */
+@Mapper
+public interface TFareFreeRuleMapper extends BaseMapper<TFareFreeRule> {
+}

+ 50 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/TFareFreeRuleService.java

@@ -0,0 +1,50 @@
+package com.ylx.massage.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ylx.massage.domain.TFareFreeRule;
+import com.ylx.massage.domain.vo.FareFreeRuleVo;
+
+import java.util.List;
+
+/**
+ * 免车费规则服务接口
+ *
+ * @author system
+ * @since 2024-01-13
+ */
+public interface TFareFreeRuleService extends IService<TFareFreeRule> {
+
+    /**
+     * 新增免车费规则
+     *
+     * @param fareFreeRule 免车费规则
+     * @return 是否成功
+     */
+    boolean addFareFreeRule(TFareFreeRule fareFreeRule);
+
+    /**
+     * 修改免车费规则
+     *
+     * @param fareFreeRule 免车费规则
+     * @return 是否成功
+     */
+    boolean updateFareFreeRule(TFareFreeRule fareFreeRule);
+
+    /**
+     * 查询免车费规则列表
+     *
+     * @param deptId 部门ID
+     * @return 免车费规则VO列表
+     */
+    List<FareFreeRuleVo> listFareFreeRules(String deptId);
+
+    /**
+     * 判断订单是否满足免车费条件
+     *
+     * @param projectIds  服务项目ID列表
+     * @param distance    订单距离(公里)
+     * @param deptId      部门ID
+     * @return true-免车费,false-不免车费
+     */
+    boolean isFareFree(List<String> projectIds, Integer distance, String deptId);
+}

+ 246 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TFareFreeRuleServiceImpl.java

@@ -0,0 +1,246 @@
+package com.ylx.massage.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ylx.common.exception.ServiceException;
+import com.ylx.common.utils.SecurityUtils;
+import com.ylx.common.utils.StringUtils;
+import com.ylx.massage.domain.TFareFreeRule;
+import com.ylx.massage.domain.TXiangmu;
+import com.ylx.massage.domain.vo.FareFreeRuleVo;
+import com.ylx.massage.domain.vo.TimeRangeVo;
+import com.ylx.massage.mapper.TFareFreeRuleMapper;
+import com.ylx.massage.service.TFareFreeRuleService;
+import com.ylx.massage.service.TXiangmuService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 免车费规则服务实现类
+ *
+ * @author system
+ * @since 2024-01-13
+ */
+@Slf4j
+@Service
+public class TFareFreeRuleServiceImpl extends ServiceImpl<TFareFreeRuleMapper, TFareFreeRule>
+        implements TFareFreeRuleService {
+
+    @Resource
+    private TXiangmuService xiangmuService;
+
+    /**
+     * 新增免车费规则
+     *
+     * @param fareFreeRule 免车费规则
+     * @return boolean 是否成功
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean addFareFreeRule(TFareFreeRule fareFreeRule) {
+        // 1. 参数校验
+        validateFareFreeRule(fareFreeRule);
+
+        // 2. 检查是否存在启用的规则
+        LambdaQueryWrapper<TFareFreeRule> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(TFareFreeRule::getTechId, fareFreeRule.getTechId()).eq(TFareFreeRule::getEnable, 1)
+                .eq(TFareFreeRule::getProjectId, fareFreeRule.getProjectId());
+        long count = this.count(wrapper);
+        if (count > 0) {
+            throw new ServiceException("已存在启用的免车费规则,请先禁用后再添加");
+        }
+
+        // 3. 设置时间
+        fareFreeRule.setCreateTime(LocalDateTime.now());
+        fareFreeRule.setUpdateTime(LocalDateTime.now());
+
+        // 4. 保存
+        return this.save(fareFreeRule);
+    }
+
+    /**
+     * 修改免车费规则
+     *
+     * @param fareFreeRule 免车费规则
+     * @return 是否成功
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean updateFareFreeRule(TFareFreeRule fareFreeRule) {
+        // 1. 参数校验
+        if (StringUtils.isBlank(fareFreeRule.getId())) {
+            throw new ServiceException("规则ID不能为空");
+        }
+        validateFareFreeRule(fareFreeRule);
+
+        // 2. 查询原规则
+        TFareFreeRule existingRule = this.getById(fareFreeRule.getId());
+        if (existingRule == null) {
+            throw new ServiceException("免车费规则不存在");
+        }
+
+
+        // 4. 如果启用规则,检查是否存在其他启用的规则
+        if (fareFreeRule.getEnable() == 1 && !existingRule.getEnable().equals(fareFreeRule.getEnable())) {
+            LambdaQueryWrapper<TFareFreeRule> wrapper = new LambdaQueryWrapper<>();
+            wrapper.eq(TFareFreeRule::getTechId, fareFreeRule.getTechId())
+                    .eq(TFareFreeRule::getEnable, 1)
+                    .ne(TFareFreeRule::getId, fareFreeRule.getId());
+            long count = this.count(wrapper);
+            if (count > 0) {
+                throw new ServiceException("已存在启用的免车费规则,请先禁用后再启用");
+            }
+        }
+
+        // 5. 更新时间
+        fareFreeRule.setUpdateTime(LocalDateTime.now());
+
+        // 6. 更新
+        return this.updateById(fareFreeRule);
+    }
+
+    /**
+     * 查询免车费规则列表
+     *
+     * @param deptId 部门ID
+     * @return 免车费规则VO列表
+     */
+    @Override
+    public List<FareFreeRuleVo> listFareFreeRules(String deptId) {
+        // 1. 查询规则列表
+        LambdaQueryWrapper<TFareFreeRule> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(TFareFreeRule::getTechId, deptId)
+                .orderByDesc(TFareFreeRule::getCreateTime);
+        List<TFareFreeRule> ruleList = this.list(wrapper);
+
+        // 2. 转换为VO
+        return ruleList.stream().map(rule -> {
+            FareFreeRuleVo vo = new FareFreeRuleVo();
+            BeanUtils.copyProperties(rule, vo);
+
+            // 转换时间段
+            if (CollectionUtil.isNotEmpty(rule.getTimeRanges())) {
+                List<TimeRangeVo> timeRangeVos = rule.getTimeRanges().stream().map(timeRange ->
+                        TimeRangeVo.builder()
+                                .startTime(timeRange.getStartTime())
+                                .endTime(timeRange.getEndTime())
+                                .build()
+                ).collect(Collectors.toList());
+                vo.setTimeRanges(timeRangeVos);
+            }
+
+            // 查询项目名称
+            if (StringUtils.isNotBlank(rule.getProjectId())) {
+                String projectNames = "";
+                TXiangmu xiangmu = xiangmuService.getById(rule.getProjectId());
+                    if (xiangmu != null && StringUtils.isNotBlank(xiangmu.getcTitle())) {
+                        projectNames = xiangmu.getcTitle();
+                    }
+                vo.setProjectNames(projectNames.isEmpty() ? null : projectNames);
+            }
+
+            return vo;
+        }).collect(Collectors.toList());
+    }
+
+    /**
+     * 判断订单是否满足免车费条件
+     *
+     * @param projectIds 服务项目ID列表
+     * @param distance   订单距离(公里)
+     * @param deptId     部门ID
+     * @return true-免车费,false-不免车费
+     */
+    @Override
+    public boolean isFareFree(List<String> projectIds, Integer distance, String deptId) {
+        // 1. 参数校验
+        if (CollectionUtil.isEmpty(projectIds) || distance == null || distance <= 0) {
+            return false;
+        }
+
+        // 2. 查询启用的免车费规则
+        LambdaQueryWrapper<TFareFreeRule> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(TFareFreeRule::getTechId, deptId)
+                .eq(TFareFreeRule::getEnable, 1)
+                .eq(TFareFreeRule::getIsDelete, 0)
+                .last("LIMIT 1");
+        TFareFreeRule rule = this.getOne(wrapper);
+
+        // 3. 如果没有启用的规则,不免车费
+        if (rule == null) {
+            return false;
+        }
+
+        // 4. 校验服务项目(订单的项目ID必须在规则的项目ID列表中)
+        if (StringUtils.isBlank(rule.getProjectId())) {
+            return false;
+        }
+        boolean projectMatch = projectIds.stream()
+                .anyMatch(projectId -> rule.getProjectId().equals(projectId));
+        if (!projectMatch) {
+            return false;
+        }
+
+        // 5. 校验距离(订单距离必须 >= 规则的最小距离)
+        if (distance < rule.getMinDistance()) {
+            return false;
+        }
+
+        // 6. 所有条件满足,免车费
+        return true;
+    }
+
+    /**
+     * 校验免车费规则参数
+     *
+     * @param fareFreeRule 免车费规则
+     */
+    private void validateFareFreeRule(TFareFreeRule fareFreeRule) {
+        // 1. 校验服务项目
+        if (StringUtils.isBlank(fareFreeRule.getProjectId())) {
+            throw new ServiceException("请至少选择一个服务项目");
+        }
+
+        // 2. 校验时间段
+        if (CollectionUtil.isEmpty(fareFreeRule.getTimeRanges())) {
+            throw new ServiceException("请至少添加一个服务时间段");
+        }
+
+        // 3. 校验时间段格式
+        for (TFareFreeRule.TimeRange timeRange : fareFreeRule.getTimeRanges()) {
+            if (StringUtils.isBlank(timeRange.getStartTime()) || StringUtils.isBlank(timeRange.getEndTime())) {
+                throw new ServiceException("时间段开始时间和结束时间不能为空");
+            }
+
+            // 校验时间格式
+            if (!timeRange.getStartTime().matches("^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$") ||
+                    !timeRange.getEndTime().matches("^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$")) {
+                throw new ServiceException("时间格式错误,请使用 HH:mm 格式(如:08:00)");
+            }
+
+            // 校验时间范围
+            if (timeRange.getStartTime().compareTo(timeRange.getEndTime()) >= 0) {
+                throw new ServiceException("开始时间必须小于结束时间");
+            }
+        }
+
+        // 4. 校验距离
+        if (fareFreeRule.getMinDistance() == null || fareFreeRule.getMinDistance() <= 0) {
+            throw new ServiceException("订单距离必须大于0");
+        }
+
+        // 5. 校验是否启用
+        if (fareFreeRule.getEnable() == null || (fareFreeRule.getEnable() != 0 && fareFreeRule.getEnable() != 1)) {
+            throw new ServiceException("是否启用参数错误");
+        }
+    }
+}