# BudgetDatabaseStatusLogServiceImpl.java

    package cloud.wconnect.rateshop.service.budgetdatabase.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.pojo.dto.ListPagedDTO;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.rateshop.cons.budgetdatabase.BudgetDatabaseStatusTypeEnum;
    import cloud.wconnect.rateshop.entity.budgetdatabase.BudgetDatabaseStatusLog;
    import cloud.wconnect.rateshop.mapper.budgetdatabase.BudgetDatabaseStatusLogMapper;
    import cloud.wconnect.rateshop.pojo.dto.budgetdatabase.StatusLogDTO;
    import cloud.wconnect.rateshop.pojo.query.budgetdatabase.StatusLogQuery;
    import cloud.wconnect.rateshop.service.budgetdatabase.IBudgetDatabaseStatusLogService;
    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 org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;

    import java.util.List;
    import java.util.Map;
    import java.util.Objects;
    import java.util.stream.Collectors;

    /**
     * <p>
     *  服务实现类
     * </p>
     *
     * @author yyt
     * @since 2025-08-13
     */
    @Service
    @DS("rate_shop")
    public class BudgetDatabaseStatusLogServiceImpl extends ServiceImpl<BudgetDatabaseStatusLogMapper, BudgetDatabaseStatusLog> implements IBudgetDatabaseStatusLogService {

        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;
        @Autowired
        private BeanMapper beanMapper;

        /**
         * 获取最新的日志
         *
         * @param propertyId 资产 id
         * @param year       年
         * @return 最新的日志
         * @author yyt
         * @date 2025/8/14
         **/
        @Override
        public BudgetDatabaseStatusLog lastLog(int propertyId, int year) {
            return getOne(new QueryWrapper<BudgetDatabaseStatusLog>().lambda()
                    .eq(BudgetDatabaseStatusLog::getPropertyId, propertyId)
                    .eq(BudgetDatabaseStatusLog::getBudgetYear, year)
                    .orderByDesc(BudgetDatabaseStatusLog::getId)
                    .last("limit 1"));
        }

        /**
         * 检查是否已经重新开启过
         *
         * @param propertyId 资产 id
         * @param year       年
         * @return true: 开启过 false: 未开启过
         * @author yyt
         * @date 2025/8/15
         **/
        @Override
        public boolean checkHasReopen(int propertyId, int year) {
            return getOne(new QueryWrapper<BudgetDatabaseStatusLog>().lambda()
                    .eq(BudgetDatabaseStatusLog::getPropertyId, propertyId)
                    .eq(BudgetDatabaseStatusLog::getBudgetYear, year)
                    .eq(BudgetDatabaseStatusLog::getType, BudgetDatabaseStatusTypeEnum.REOPEN.getCode())
                    .select(BudgetDatabaseStatusLog::getId)
                    .last("limit 1")) != null;
        }

        /**
         * 查询状态修改记录
         *
         * @param propertyId 资产 id
         * @param year       年
         * @param query      查询条件
         * @return 状态修改记录
         * @author yyt
         * @date 2025/8/15
         **/
        @Override
        public ListPagedDTO<StatusLogDTO> listStatusLog(int propertyId, int year, StatusLogQuery query) {
            LambdaQueryWrapper<BudgetDatabaseStatusLog> sql = new QueryWrapper<BudgetDatabaseStatusLog>().lambda()
                    .eq(BudgetDatabaseStatusLog::getPropertyId, propertyId)
                    .eq(BudgetDatabaseStatusLog::getBudgetYear, year)
                    .eq(Objects.nonNull(query.getType()), BudgetDatabaseStatusLog::getType, query.getType());

            long total;
            List<BudgetDatabaseStatusLog> statusLogs;
            if (Objects.nonNull(query.getPage()) && Objects.nonNull(query.getSize())) {
                Page<BudgetDatabaseStatusLog> page = page(new Page<>(query.getPage(), query.getSize()),
                        sql.orderByDesc(BudgetDatabaseStatusLog::getId));
                total = page.getTotal();
                statusLogs = page.getRecords();
            } else {
                statusLogs = list(sql);
                total = statusLogs.size();
            }
            if (CollectionUtils.isEmpty(statusLogs)) {
                return new ListPagedDTO<>();
            }

            Map<Integer, UserDTO> userById = userInternalService.getUsers(propertyI18nRedisService.get(propertyId).getTenantId(),
                            statusLogs.stream().map(BudgetDatabaseStatusLog::getUpdatedBy).distinct().collect(Collectors.toList()))
                    .stream().collect(Collectors.toMap(UserDTO::getId, v -> v));

            return new ListPagedDTO<>(total, beanMapper.mapList(statusLogs, StatusLogDTO.class,
                    dto -> {
                        UserDTO userDTO = userById.get(dto.getUpdatedBy());
                        dto.setUpdatedName(userDTO.getName());
                        dto.setAvatar(userDTO.getAvatar());
                    }));
        }

        /**
         * 保存操作记录
         *
         * @param propertyId 资产 id
         * @param year       年
         * @param userId     操作人
         * @param type       1.complete，2.reopen
         * @author yyt
         * @date 2025/8/15
         **/
        @Override
        public void saveLog(int propertyId, int year, int userId, Integer type) {
            save(new BudgetDatabaseStatusLog()
                    .setPropertyId(propertyId)
                    .setBudgetYear(year)
                    .setType(type)
                    .setUpdatedBy(userId)
                    .setUpdatedTime(DateTimeUtils.nowTimestamp()));
        }

    }