# SalaryPayConfigServiceImpl.java

    package cloud.wconnect.workperformance.service.sva.setting.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.pojo.dto.ListPagedDTO;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.workperformance.entity.sva.setting.SalaryPayConfig;
    import cloud.wconnect.workperformance.mapper.sva.setting.SalaryPayConfigMapper;
    import cloud.wconnect.workperformance.pojo.dto.sva.salarypay.SalaryPayDTO;
    import cloud.wconnect.workperformance.pojo.dto.sva.salarypay.SalaryPayHistoryDTO;
    import cloud.wconnect.workperformance.service.sva.setting.ISalaryPayConfigService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import jakarta.annotation.Resource;
    import org.springframework.stereotype.Service;

    import java.text.MessageFormat;
    import java.util.Objects;

    /**
     * <p>
     * 服务实现类：Salary Pay 配置
     * </p>
     *
     * @author zc
     * @since 2023-03-10
     */
    @Service
    @DS("work_performance")
    public class SalaryPayConfigServiceImpl extends ServiceImpl<SalaryPayConfigMapper, SalaryPayConfig> implements ISalaryPayConfigService {
        @Resource
        private BeanMapper beanMapper;

        /**
         * 新增 salary pay 数据
         *
         * @param propertyId   资产 id
         * @param operatorId   操作人 id
         * @param salaryPayDTO salary pay 数据
         * @author zc
         * @date 2023/3/11
         */
        @Override
        public int insert(int propertyId, int operatorId, SalaryPayDTO salaryPayDTO) {
            LambdaQueryWrapper<SalaryPayConfig> queryWrapper = new QueryWrapper<SalaryPayConfig>().lambda()
                    .eq(SalaryPayConfig::getPropertyId, propertyId)
                    .eq(SalaryPayConfig::getStartingDate, salaryPayDTO.getStartingDate())
                    .select(SalaryPayConfig::getId);
            if (count(queryWrapper) > 0) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_EXISTED,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The salary pay config startingDate has existed in current property; startingDate: " + salaryPayDTO.getStartingDate());
            }

            SalaryPayConfig salaryPayConfig = beanMapper.map(salaryPayDTO, SalaryPayConfig.class);
            salaryPayConfig.setPropertyId(propertyId);
            salaryPayConfig.setCreatedBy(operatorId);
            salaryPayConfig.setCreatedTime(DateTimeUtils.nowTimestamp());
            save(salaryPayConfig);

            return salaryPayConfig.getId();
        }

        /**
         * 编辑 salary pay 数据
         *
         * @param propertyId   资产 id
         * @param operatorId   操作人 id
         * @param salaryPayDTO salary pay 数据
         * @author zc
         * @date 2023/3/11
         */
        @Override
        public int update(int propertyId, int operatorId, SalaryPayDTO salaryPayDTO) {
            LambdaQueryWrapper<SalaryPayConfig> queryWrapper = new QueryWrapper<SalaryPayConfig>().lambda()
                    .ne(SalaryPayConfig::getId, salaryPayDTO.getId())
                    .eq(SalaryPayConfig::getPropertyId, propertyId)
                    .eq(SalaryPayConfig::getStartingDate, salaryPayDTO.getStartingDate())
                    .select(SalaryPayConfig::getId);
            if (count(queryWrapper) > 0) {
                throw new BadRequestException(CommonErrorI18nConstant.DATA_EXISTED,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The salary pay config startingDate has existed in current property; startingDate: " + salaryPayDTO.getStartingDate());
            }

            SalaryPayConfig salaryPayConfig = beanMapper.map(salaryPayDTO, SalaryPayConfig.class);
            salaryPayConfig.setId(salaryPayDTO.getId());
            salaryPayConfig.setLastUpdatedBy(operatorId);
            salaryPayConfig.setLastUpdatedTime(DateTimeUtils.nowTimestamp());
            updateById(salaryPayConfig);

            return salaryPayConfig.getId();
        }

        /**
         * 获取 Salary Pay 历史版本列表
         *
         * @param propertyId property id
         * @param page       当前页码
         * @param size       每页条数
         * @return Salary Pay 历史数据
         * @author zc
         * @date 2023/3/12
         */
        @Override
        public ListPagedDTO<SalaryPayHistoryDTO> listHistories(int propertyId, int page, int size) {
            LambdaQueryWrapper<SalaryPayConfig> queryWrapper = new QueryWrapper<SalaryPayConfig>().lambda()
                    .eq(SalaryPayConfig::getPropertyId, propertyId)
                    .orderByDesc(SalaryPayConfig::getStartingDate);
            Page<SalaryPayConfig> paged = page(new Page<>(page, size), queryWrapper);
            if (paged.getTotal() == 0L) {
                return new ListPagedDTO<>();
            }
            return new ListPagedDTO<>(paged.getTotal(), beanMapper.mapList(paged.getRecords(), SalaryPayHistoryDTO.class));
        }

        /**
         * 获取当前应用的 Salary Pay 数据
         *
         * @param propertyId property id
         * @param targetDate 目标日期
         * @return Salary Pay
         * @author zc
         * @date 2023/3/12
         */
        @Override
        public SalaryPayDTO getCurrent(int propertyId, long targetDate) {
            LambdaQueryWrapper<SalaryPayConfig> queryWrapper = new QueryWrapper<SalaryPayConfig>().lambda()
                    .eq(SalaryPayConfig::getPropertyId, propertyId)
                    .le(SalaryPayConfig::getStartingDate, targetDate)
                    .orderByDesc(SalaryPayConfig::getStartingDate)
                    .last("limit 1");
            SalaryPayConfig salaryPayConfig = getOne(queryWrapper);
            if (Objects.isNull(salaryPayConfig)) {
                return null;
            }

            return beanMapper.map(salaryPayConfig, SalaryPayDTO.class);
        }

        /**
         * 获取最新版本的 Salary Pay 数据
         *
         * @param propertyId property id
         * @return Salary Pay
         * @author zc
         * @date 2023/3/12
         */
        @Override
        public SalaryPayDTO getLatest(int propertyId) {
            LambdaQueryWrapper<SalaryPayConfig> queryWrapper = new QueryWrapper<SalaryPayConfig>().lambda()
                    .eq(SalaryPayConfig::getPropertyId, propertyId)
                    .orderByDesc(SalaryPayConfig::getStartingDate)
                    .last("limit 1");
            SalaryPayConfig salaryPayConfig = getOne(queryWrapper);
            if (Objects.isNull(salaryPayConfig)) {
                return null;
            }

            return beanMapper.map(salaryPayConfig, SalaryPayDTO.class);
        }

        /**
         * 获取有效的 Salary Pay 数据
         *
         * @param propertyId property id
         * @param targetDate 目标日期
         * @param isGreater  0: 获取大于目标日期的数据；1: 获取小于目标日期的数据；2: 获取等于目标日期的数据
         * @return Salary Pay
         * @author zc
         * @date 2023/3/17
         */
        @Override
        public SalaryPayDTO getEffective(int propertyId, long targetDate, int isGreater) {
            LambdaQueryWrapper<SalaryPayConfig> queryWrapper = new QueryWrapper<SalaryPayConfig>().lambda()
                    .eq(SalaryPayConfig::getPropertyId, propertyId);
            if (SalaryPayDTO.GREATER_THAN == isGreater) {
                queryWrapper.gt(SalaryPayConfig::getStartingDate, targetDate)
                        .orderByAsc(SalaryPayConfig::getStartingDate);
            } else if (SalaryPayDTO.LESS_THAN == isGreater) {
                queryWrapper.lt(SalaryPayConfig::getStartingDate, targetDate)
                        .orderByDesc(SalaryPayConfig::getStartingDate);
            } else if (SalaryPayDTO.EQUAL_TO == isGreater) {
                queryWrapper.eq(SalaryPayConfig::getStartingDate, targetDate);
            }

            SalaryPayConfig salaryPayConfig = getOne(queryWrapper.last("limit 1"));
            if (Objects.isNull(salaryPayConfig)) {
                return null;
            }

            return beanMapper.map(salaryPayConfig, SalaryPayDTO.class);
        }

        /**
         * 校验数据归属
         *
         * @param propertyId      property id
         * @param originSalaryPay Salary Pay 数据
         * @author zc
         * @date 2025/7/31
         */
        @Override
        public void checkBelong(int propertyId, SalaryPayConfig originSalaryPay) {
            if (!originSalaryPay.getPropertyId().equals(propertyId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The requested does not belong to this property; propertyId:{0}; requestedPropertyId:{1}",
                                propertyId, originSalaryPay.getPropertyId()));
            }
        }

    }