Kaynağa Gözat

开发完成考勤配置相关的接口

jinshihui 1 hafta önce
ebeveyn
işleme
6a7d18d2ea

+ 115 - 0
nightFragrance-massage/src/main/java/com/ylx/attendanceconfig/controller/AttendanceConfigController.java

@@ -0,0 +1,115 @@
+package com.ylx.attendanceconfig.controller;
+
+import com.ylx.attendanceconfig.domain.dto.AttendanceRuleAddDTO;
+import com.ylx.attendanceconfig.domain.vo.AttendanceRuleDetailVO;
+import com.ylx.attendanceconfig.service.AttendanceConfigService;
+import com.ylx.common.annotation.Log;
+import com.ylx.common.core.domain.R;
+import com.ylx.common.enums.BusinessType;
+import com.ylx.common.exception.ServiceException;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Slf4j
+@RestController
+@RequestMapping("/attendance/config")
+@Api(tags = {"考勤规则配置"})
+public class AttendanceConfigController {
+
+    @Resource
+    private AttendanceConfigService attendanceConfigService;
+
+    /**
+     * 新增考勤规则
+     *
+     * @param dto 考勤规则参数
+     * @return 操作结果
+     */
+    @PostMapping
+    @ApiOperation("新增考勤规则")
+    @Log(title = "新增考勤规则", businessType = BusinessType.INSERT)
+    public R<?> add(@Validated @RequestBody AttendanceRuleAddDTO dto) {
+        try {
+            attendanceConfigService.addAttendanceRule(dto);
+            return R.ok();
+        } catch (ServiceException e) {
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("新增考勤规则异常", e);
+            return R.fail("新增考勤规则失败");
+        }
+    }
+
+    /**
+     * 查询全部考勤规则
+     *
+     * @return R<List<AttendanceRuleDetailVO>> 考勤规则详情集合
+     */
+    @GetMapping
+    @ApiOperation("查询全部考勤规则")
+    public R<List<AttendanceRuleDetailVO>> query() {
+        try {
+            List<AttendanceRuleDetailVO> list = attendanceConfigService.listAttendanceRules();
+            return R.ok(list);
+        } catch (ServiceException e) {
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("查询全部考勤规则异常", e);
+            return R.fail("查询全部考勤规则失败");
+        }
+    }
+
+    /**
+     * 删除考勤规则
+     *
+     * @param id 考勤规则ID
+     * @return 操作结果
+     */
+    @DeleteMapping("/{id}")
+    @ApiOperation("删除考勤规则")
+    @Log(title = "删除考勤规则", businessType = BusinessType.DELETE)
+    public R<?> delete(@PathVariable("id") Long id) {
+        try {
+            attendanceConfigService.deleteAttendanceRule(id);
+            return R.ok();
+        } catch (ServiceException e) {
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("删除考勤规则异常", e);
+            return R.fail("删除考勤规则失败");
+        }
+    }
+
+    /**
+     * 删除考勤扣款区间
+     *
+     * @param id 扣款区间ID
+     * @return 操作结果
+     */
+    @DeleteMapping("/deduction/{id}")
+    @ApiOperation("删除考勤扣款区间")
+    @Log(title = "删除考勤扣款区间", businessType = BusinessType.DELETE)
+    public R<?> deleteDeduction(@PathVariable("id") Long id) {
+        try {
+            attendanceConfigService.deleteDeductionRule(id);
+            return R.ok();
+        } catch (ServiceException e) {
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("删除考勤扣款区间异常", e);
+            return R.fail("删除考勤扣款区间失败");
+        }
+    }
+}

+ 110 - 0
nightFragrance-massage/src/main/java/com/ylx/attendanceconfig/domain/AttendanceDeductionRule.java

@@ -0,0 +1,110 @@
+package com.ylx.attendanceconfig.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+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 io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 考勤扣款区间规则表
+ */
+@Data
+@ApiModel("考勤扣款区间规则表")
+@TableName("attendance_deduction_rule")
+public class AttendanceDeductionRule implements Serializable {
+    private static final long serialVersionUID = -3851089045114907220L;
+
+    /**
+     * 主键ID
+     */
+    @ApiModelProperty("主键ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 考勤规则ID,关联attendance_rule.id
+     */
+    @ApiModelProperty("考勤规则ID,关联attendance_rule.id")
+    @TableField("rule_id")
+    private Long ruleId;
+
+    /**
+     * 规则类型:1=早退时长扣款
+     */
+    @ApiModelProperty("规则类型:1=早退时长扣款")
+    @TableField("rule_type")
+    private Integer ruleType;
+
+    /**
+     * 开始分钟数,包含该值
+     */
+    @ApiModelProperty("开始分钟数,包含该值")
+    @TableField("start_minutes")
+    private Integer startMinutes;
+
+    /**
+     * 结束分钟数,包含该值
+     */
+    @ApiModelProperty("结束分钟数,包含该值")
+    @TableField("end_minutes")
+    private Integer endMinutes;
+
+    /**
+     * 扣款金额,单位:元
+     */
+    @ApiModelProperty("扣款金额,单位:元")
+    @TableField("deduct_amount")
+    private BigDecimal deductAmount;
+
+    /**
+     * 排序
+     */
+    @ApiModelProperty("排序")
+    @TableField("sort_order")
+    private Integer sortOrder;
+
+    /**
+     * 创建人
+     */
+    @ApiModelProperty("创建人")
+    @TableField("create_by")
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    @ApiModelProperty("创建时间")
+    @TableField(value = "create_time", fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    /**
+     * 更新人
+     */
+    @ApiModelProperty("更新人")
+    @TableField("update_by")
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    @ApiModelProperty("更新时间")
+    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    /**
+     * 是否删除:0=否,1=是
+     */
+    @ApiModelProperty("是否删除:0=否,1=是")
+    @TableField("is_delete")
+    @TableLogic
+    private Integer isDelete;
+}

+ 103 - 0
nightFragrance-massage/src/main/java/com/ylx/attendanceconfig/domain/AttendanceRule.java

@@ -0,0 +1,103 @@
+package com.ylx.attendanceconfig.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+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 io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 考勤规则主表
+ */
+@Data
+@ApiModel("考勤规则主表")
+@TableName("attendance_rule")
+public class AttendanceRule implements Serializable {
+    private static final long serialVersionUID = 2048164226986084497L;
+
+    /**
+     * 主键ID
+     */
+    @ApiModelProperty("主键ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 规则名称
+     */
+    @ApiModelProperty("规则名称")
+    @TableField("rule_name")
+    private String ruleName;
+
+    /**
+     * 商户ID,为空表示平台默认规则
+     */
+    @ApiModelProperty("商户ID,为空表示平台默认规则")
+    @TableField("merchant_id")
+    private String merchantId;
+
+    /**
+     * 基本工作时长,单位:小时
+     */
+    @ApiModelProperty("基本工作时长,单位:小时")
+    @TableField("basic_work_hours")
+    private BigDecimal basicWorkHours;
+
+    /**
+     * 是否启用工作时长规则:0=无,1=有
+     */
+    @ApiModelProperty("是否启用工作时长规则:0=无,1=有")
+    @TableField("work_duration_rule_enabled")
+    private Integer workDurationRuleEnabled;
+
+    /**
+     * 状态:0=停用,1=启用
+     */
+    @ApiModelProperty("状态:0=停用,1=启用")
+    @TableField("status")
+    private Integer status;
+
+    /**
+     * 创建人
+     */
+    @ApiModelProperty("创建人")
+    @TableField("create_by")
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    @ApiModelProperty("创建时间")
+    @TableField(value = "create_time", fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    /**
+     * 更新人
+     */
+    @ApiModelProperty("更新人")
+    @TableField("update_by")
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    @ApiModelProperty("更新时间")
+    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    /**
+     * 是否删除:0=否,1=是
+     */
+    @ApiModelProperty("是否删除:0=否,1=是")
+    @TableField("is_delete")
+    @TableLogic
+    private Integer isDelete;
+}

+ 38 - 0
nightFragrance-massage/src/main/java/com/ylx/attendanceconfig/domain/dto/AttendanceDeductionRuleDTO.java

@@ -0,0 +1,38 @@
+package com.ylx.attendanceconfig.domain.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.DecimalMin;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+@ApiModel("考勤扣款区间DTO")
+public class AttendanceDeductionRuleDTO implements Serializable {
+    private static final long serialVersionUID = -8789319415530497294L;
+
+    @ApiModelProperty("扣款区间ID,新增时可不传")
+    private Long id;
+
+    @ApiModelProperty("规则类型:1=早退时长扣款,不传默认1")
+    private Integer ruleType;
+
+    @NotNull(message = "开始分钟数不能为空")
+    @Min(value = 1, message = "开始分钟数必须大于0")
+    @ApiModelProperty(value = "开始分钟数,包含该值", required = true)
+    private Integer startMinutes;
+
+    @NotNull(message = "结束分钟数不能为空")
+    @Min(value = 1, message = "结束分钟数必须大于0")
+    @ApiModelProperty(value = "结束分钟数,包含该值", required = true)
+    private Integer endMinutes;
+
+    @NotNull(message = "扣款金额不能为空")
+    @DecimalMin(value = "0", message = "扣款金额不能小于0")
+    @ApiModelProperty(value = "扣款金额,单位:元", required = true)
+    private BigDecimal deductAmount;
+}

+ 49 - 0
nightFragrance-massage/src/main/java/com/ylx/attendanceconfig/domain/dto/AttendanceRuleAddDTO.java

@@ -0,0 +1,49 @@
+package com.ylx.attendanceconfig.domain.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.Valid;
+import javax.validation.constraints.DecimalMin;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@ApiModel("考勤规则新增DTO")
+public class AttendanceRuleAddDTO implements Serializable {
+    private static final long serialVersionUID = 1163485126326629827L;
+
+    @ApiModelProperty("规则名称,不传默认:默认考勤规则")
+    private String ruleName;
+
+    @ApiModelProperty("商户ID,为空表示平台默认规则")
+    private String merchantId;
+
+    @NotNull(message = "基本工作时长不能为空")
+    @DecimalMin(value = "0.01", message = "基本工作时长必须大于0")
+    @ApiModelProperty(value = "基本工作时长,单位:小时", required = true)
+    private BigDecimal basicWorkHours;
+
+    /**
+     * 是否启用工作时长规则:0=无,1=有
+     */
+    @NotNull(message = "工作时长规则不能为空")
+    @ApiModelProperty(value = "是否启用工作时长规则:0=无,1=有", required = true)
+    private Integer workDurationRuleEnabled;
+
+    /**
+     * 状态:0=停用,1=启用
+     */
+    @ApiModelProperty("状态:0=停用,1=启用,不传默认启用")
+    private Integer status;
+
+    /**
+     * 扣款区间规则集合
+     */
+    @Valid
+    @ApiModelProperty("扣款区间规则集合")
+    private List<AttendanceDeductionRuleDTO> deductionRules;
+}

+ 32 - 0
nightFragrance-massage/src/main/java/com/ylx/attendanceconfig/domain/vo/AttendanceDeductionRuleVO.java

@@ -0,0 +1,32 @@
+package com.ylx.attendanceconfig.domain.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+@ApiModel("考勤扣款区间VO")
+public class AttendanceDeductionRuleVO implements Serializable {
+    private static final long serialVersionUID = -5881577398957998820L;
+
+    @ApiModelProperty("扣款区间ID")
+    private Long id;
+
+    @ApiModelProperty("规则类型:1=早退时长扣款")
+    private Integer ruleType;
+
+    @ApiModelProperty("开始分钟数,包含该值")
+    private Integer startMinutes;
+
+    @ApiModelProperty("结束分钟数,包含该值")
+    private Integer endMinutes;
+
+    @ApiModelProperty("扣款金额,单位:元")
+    private BigDecimal deductAmount;
+
+    @ApiModelProperty("排序")
+    private Integer sortOrder;
+}

+ 46 - 0
nightFragrance-massage/src/main/java/com/ylx/attendanceconfig/domain/vo/AttendanceRuleDetailVO.java

@@ -0,0 +1,46 @@
+package com.ylx.attendanceconfig.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+@ApiModel("考勤规则详情VO")
+public class AttendanceRuleDetailVO implements Serializable {
+    private static final long serialVersionUID = -7242343396476539324L;
+
+    @ApiModelProperty("考勤规则ID")
+    private Long id;
+
+    @ApiModelProperty("规则名称")
+    private String ruleName;
+
+    @ApiModelProperty("商户ID,为空表示平台默认规则")
+    private String merchantId;
+
+    @ApiModelProperty("基本工作时长,单位:小时")
+    private BigDecimal basicWorkHours;
+
+    @ApiModelProperty("是否启用工作时长规则:0=无,1=有")
+    private Integer workDurationRuleEnabled;
+
+    @ApiModelProperty("状态:0=停用,1=启用")
+    private Integer status;
+
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty("扣款区间规则集合")
+    private List<AttendanceDeductionRuleVO> deductionRules;
+}

+ 7 - 0
nightFragrance-massage/src/main/java/com/ylx/attendanceconfig/mapper/AttendanceDeductionRuleMapper.java

@@ -0,0 +1,7 @@
+package com.ylx.attendanceconfig.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ylx.attendanceconfig.domain.AttendanceDeductionRule;
+
+public interface AttendanceDeductionRuleMapper extends BaseMapper<AttendanceDeductionRule> {
+}

+ 7 - 0
nightFragrance-massage/src/main/java/com/ylx/attendanceconfig/mapper/AttendanceRuleMapper.java

@@ -0,0 +1,7 @@
+package com.ylx.attendanceconfig.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ylx.attendanceconfig.domain.AttendanceRule;
+
+public interface AttendanceRuleMapper extends BaseMapper<AttendanceRule> {
+}

+ 17 - 0
nightFragrance-massage/src/main/java/com/ylx/attendanceconfig/service/AttendanceConfigService.java

@@ -0,0 +1,17 @@
+package com.ylx.attendanceconfig.service;
+
+import com.ylx.attendanceconfig.domain.dto.AttendanceRuleAddDTO;
+import com.ylx.attendanceconfig.domain.vo.AttendanceRuleDetailVO;
+
+import java.util.List;
+
+public interface AttendanceConfigService {
+
+    void addAttendanceRule(AttendanceRuleAddDTO dto);
+
+    List<AttendanceRuleDetailVO> listAttendanceRules();
+
+    void deleteAttendanceRule(Long id);
+
+    void deleteDeductionRule(Long id);
+}

+ 220 - 0
nightFragrance-massage/src/main/java/com/ylx/attendanceconfig/service/impl/AttendanceConfigServiceImpl.java

@@ -0,0 +1,220 @@
+package com.ylx.attendanceconfig.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.ylx.attendanceconfig.domain.AttendanceDeductionRule;
+import com.ylx.attendanceconfig.domain.AttendanceRule;
+import com.ylx.attendanceconfig.domain.dto.AttendanceDeductionRuleDTO;
+import com.ylx.attendanceconfig.domain.dto.AttendanceRuleAddDTO;
+import com.ylx.attendanceconfig.domain.vo.AttendanceDeductionRuleVO;
+import com.ylx.attendanceconfig.domain.vo.AttendanceRuleDetailVO;
+import com.ylx.attendanceconfig.mapper.AttendanceDeductionRuleMapper;
+import com.ylx.attendanceconfig.mapper.AttendanceRuleMapper;
+import com.ylx.attendanceconfig.service.AttendanceConfigService;
+import com.ylx.common.exception.ServiceException;
+import com.ylx.common.utils.SecurityUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class AttendanceConfigServiceImpl implements AttendanceConfigService {
+
+    @Resource
+    private AttendanceRuleMapper attendanceRuleMapper;
+
+    @Resource
+    private AttendanceDeductionRuleMapper attendanceDeductionRuleMapper;
+
+    private static final int NOT_DELETE = 0;
+    private static final int DELETE = 1;
+    private static final int ENABLED = 1;
+    private static final int DISABLED = 0;
+    private static final int EARLY_LEAVE_DEDUCTION = 1;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void addAttendanceRule(AttendanceRuleAddDTO dto) {
+        checkRuleParam(dto);
+
+        AttendanceRule rule = new AttendanceRule();
+        rule.setRuleName(StrUtil.blankToDefault(StrUtil.trim(dto.getRuleName()), "默认考勤规则"));
+        rule.setMerchantId(StrUtil.trim(dto.getMerchantId()));
+        rule.setBasicWorkHours(dto.getBasicWorkHours());
+        rule.setWorkDurationRuleEnabled(dto.getWorkDurationRuleEnabled());
+        rule.setStatus(ObjectUtil.defaultIfNull(dto.getStatus(), ENABLED));
+        rule.setIsDelete(NOT_DELETE);
+        rule.setCreateBy(SecurityUtils.getUsername());
+        rule.setUpdateBy(SecurityUtils.getUsername());
+
+        int insertRuleResult = attendanceRuleMapper.insert(rule);
+        if (insertRuleResult <= 0 || ObjectUtil.isNull(rule.getId())) {
+            throw new ServiceException("新增考勤规则失败");
+        }
+
+        if (dto.getWorkDurationRuleEnabled() == ENABLED) {
+            List<AttendanceDeductionRuleDTO> sortedRules = sortDeductionRules(dto.getDeductionRules());
+            for (int i = 0; i < sortedRules.size(); i++) {
+                AttendanceDeductionRuleDTO deductionDto = sortedRules.get(i);
+                AttendanceDeductionRule deductionRule = new AttendanceDeductionRule();
+                deductionRule.setRuleId(rule.getId());
+                deductionRule.setRuleType(ObjectUtil.defaultIfNull(deductionDto.getRuleType(), EARLY_LEAVE_DEDUCTION));
+                deductionRule.setStartMinutes(deductionDto.getStartMinutes());
+                deductionRule.setEndMinutes(deductionDto.getEndMinutes());
+                deductionRule.setDeductAmount(deductionDto.getDeductAmount());
+                deductionRule.setSortOrder(i + 1);
+                deductionRule.setIsDelete(NOT_DELETE);
+                deductionRule.setCreateBy(SecurityUtils.getUsername());
+                deductionRule.setUpdateBy(SecurityUtils.getUsername());
+
+                int insertDeductionResult = attendanceDeductionRuleMapper.insert(deductionRule);
+                if (insertDeductionResult <= 0) {
+                    throw new ServiceException("新增考勤扣款区间失败");
+                }
+            }
+        }
+    }
+
+    @Override
+    public List<AttendanceRuleDetailVO> listAttendanceRules() {
+        List<AttendanceRule> ruleList = attendanceRuleMapper.selectList(new LambdaQueryWrapper<AttendanceRule>()
+                .orderByDesc(AttendanceRule::getCreateTime));
+        return ruleList.stream()
+                .map(this::toDetailVO)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteAttendanceRule(Long id) {
+        if (ObjectUtil.isNull(id) || id <= 0) {
+            throw new ServiceException("考勤规则ID不正确");
+        }
+        AttendanceRule rule = attendanceRuleMapper.selectOne(new LambdaQueryWrapper<AttendanceRule>()
+                .eq(AttendanceRule::getId, id)
+                .eq(AttendanceRule::getIsDelete, NOT_DELETE));
+        if (ObjectUtil.isNull(rule)) {
+            throw new ServiceException("考勤规则不存在或已删除");
+        }
+
+        String username = SecurityUtils.getUsername();
+        LocalDateTime now = LocalDateTime.now();
+        int updateRuleResult = attendanceRuleMapper.update(null, new LambdaUpdateWrapper<AttendanceRule>()
+                .eq(AttendanceRule::getId, id)
+                .eq(AttendanceRule::getIsDelete, NOT_DELETE)
+                .set(AttendanceRule::getIsDelete, DELETE)
+                .set(AttendanceRule::getUpdateBy, username)
+                .set(AttendanceRule::getUpdateTime, now));
+        if (updateRuleResult <= 0) {
+            throw new ServiceException("删除考勤规则失败");
+        }
+
+        attendanceDeductionRuleMapper.update(null, new LambdaUpdateWrapper<AttendanceDeductionRule>()
+                .eq(AttendanceDeductionRule::getRuleId, id)
+                .eq(AttendanceDeductionRule::getIsDelete, NOT_DELETE)
+                .set(AttendanceDeductionRule::getIsDelete, DELETE)
+                .set(AttendanceDeductionRule::getUpdateBy, username)
+                .set(AttendanceDeductionRule::getUpdateTime, now));
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteDeductionRule(Long id) {
+        if (ObjectUtil.isNull(id) || id <= 0) {
+            throw new ServiceException("扣款区间ID不正确");
+        }
+        AttendanceDeductionRule deductionRule = attendanceDeductionRuleMapper.selectOne(
+                new LambdaQueryWrapper<AttendanceDeductionRule>()
+                        .eq(AttendanceDeductionRule::getId, id));
+        if (ObjectUtil.isNull(deductionRule)) {
+            throw new ServiceException("扣款区间不存在或已删除");
+        }
+
+        int updateResult = attendanceDeductionRuleMapper.deleteById(id);
+        if (updateResult <= 0) {
+            throw new ServiceException("删除扣款区间失败");
+        }
+    }
+
+    private void checkRuleParam(AttendanceRuleAddDTO dto) {
+        if (ObjectUtil.isNull(dto)) {
+            throw new ServiceException("考勤规则参数不能为空");
+        }
+        if (ObjectUtil.isNull(dto.getBasicWorkHours()) || dto.getBasicWorkHours().compareTo(BigDecimal.ZERO) <= 0) {
+            throw new ServiceException("基本工作时长必须大于0");
+        }
+        if (dto.getWorkDurationRuleEnabled() != ENABLED && dto.getWorkDurationRuleEnabled() != DISABLED) {
+            throw new ServiceException("工作时长规则值不正确");
+        }
+        if (ObjectUtil.isNotNull(dto.getStatus()) && dto.getStatus() != ENABLED && dto.getStatus() != DISABLED) {
+            throw new ServiceException("考勤规则状态值不正确");
+        }
+        if (dto.getWorkDurationRuleEnabled() == ENABLED) {
+            checkDeductionRules(dto.getDeductionRules());
+        }
+    }
+
+    private void checkDeductionRules(List<AttendanceDeductionRuleDTO> deductionRules) {
+        if (CollectionUtil.isEmpty(deductionRules)) {
+            throw new ServiceException("启用工作时长规则时,扣款区间不能为空");
+        }
+        List<AttendanceDeductionRuleDTO> sortedRules = sortDeductionRules(deductionRules);
+        int expectedStartMinutes = 1;
+        for (AttendanceDeductionRuleDTO deductionRule : sortedRules) {
+            if (ObjectUtil.defaultIfNull(deductionRule.getRuleType(), EARLY_LEAVE_DEDUCTION) != EARLY_LEAVE_DEDUCTION) {
+                throw new ServiceException("扣款规则类型不正确");
+            }
+            if (ObjectUtil.isNull(deductionRule.getStartMinutes()) || deductionRule.getStartMinutes() <= 0) {
+                throw new ServiceException("开始分钟数必须大于0");
+            }
+            if (ObjectUtil.isNull(deductionRule.getEndMinutes()) || deductionRule.getEndMinutes() < deductionRule.getStartMinutes()) {
+                throw new ServiceException("结束分钟数不能小于开始分钟数");
+            }
+            if (ObjectUtil.isNull(deductionRule.getDeductAmount()) || deductionRule.getDeductAmount().compareTo(BigDecimal.ZERO) < 0) {
+                throw new ServiceException("扣款金额不能小于0");
+            }
+            if (deductionRule.getStartMinutes() != expectedStartMinutes) {
+                throw new ServiceException("扣款区间必须从1分钟开始且连续");
+            }
+            expectedStartMinutes = deductionRule.getEndMinutes() + 1;
+        }
+    }
+
+    private List<AttendanceDeductionRuleDTO> sortDeductionRules(List<AttendanceDeductionRuleDTO> deductionRules) {
+        return deductionRules.stream()
+                .sorted(Comparator.comparing(AttendanceDeductionRuleDTO::getStartMinutes))
+                .collect(Collectors.toList());
+    }
+
+    private AttendanceRuleDetailVO toDetailVO(AttendanceRule rule) {
+        AttendanceRuleDetailVO vo = new AttendanceRuleDetailVO();
+        BeanUtil.copyProperties(rule, vo);
+        vo.setDeductionRules(getDeductionRuleVOList(rule.getId()));
+        return vo;
+    }
+
+    private List<AttendanceDeductionRuleVO> getDeductionRuleVOList(Long ruleId) {
+        List<AttendanceDeductionRule> deductionRules = attendanceDeductionRuleMapper.selectList(
+                new LambdaQueryWrapper<AttendanceDeductionRule>()
+                        .eq(AttendanceDeductionRule::getRuleId, ruleId)
+                        .orderByAsc(AttendanceDeductionRule::getSortOrder)
+                        .orderByAsc(AttendanceDeductionRule::getStartMinutes));
+        return deductionRules.stream().map(entity -> {
+            AttendanceDeductionRuleVO vo = new AttendanceDeductionRuleVO();
+            BeanUtil.copyProperties(entity, vo);
+            return vo;
+        }).collect(Collectors.toList());
+    }
+}

+ 2 - 1
nightFragrance-massage/src/main/java/com/ylx/giftCard/service/IGiftCardService.java

@@ -14,12 +14,13 @@ import com.ylx.giftCard.domain.vo.GiftCardManagePageVO;
 import com.ylx.giftCard.domain.vo.GiftCardVO;
 
 import java.util.List;
+import java.util.Map;
 
 public interface IGiftCardService {
 
     Page<GiftCardVO> getGiftCardPage(Page<GiftCard> page);
 
-    boolean purchaseGiftCard(GiftCardPurchaseDTO dto);
+    Map<String, Object> purchaseGiftCard(GiftCardPurchaseDTO dto);
 
     GiftCardDetailVO getGiftCardDetail(Long id);
 

+ 1 - 0
nightFragrance-massage/src/main/java/com/ylx/giftCard/service/impl/GiftCardServiceImpl.java

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ylx.common.core.domain.model.WxLoginUser;
 import com.ylx.common.exception.ServiceException;
 import com.ylx.common.utils.DateUtils;
 import com.ylx.common.utils.SecurityUtils;