# MonthlyReportController.java

    package cloud.wconnect.workperformance.controller.monthlyreport;

    import cloud.wconnect.commonlib.annotation.ApiId;
    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.component.SessionContext;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.cons.CommonFieldI18nConstant;
    import cloud.wconnect.commonlib.cons.SystemPlatformEnum;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.commonlib.util.UploadUtils;
    import cloud.wconnect.workperformance.cons.monthlyreport.AreaEnum;
    import cloud.wconnect.workperformance.cons.monthlyreport.ReportTypeEnum;
    import cloud.wconnect.workperformance.entity.monthlyreport.MonthlyReport;
    import cloud.wconnect.workperformance.pojo.dto.monthlyreport.MonthlyReportImportDTO;
    import cloud.wconnect.workperformance.pojo.vo.monthlyreport.AreaVO;
    import cloud.wconnect.workperformance.pojo.vo.monthlyreport.MonthlyReportVO;
    import cloud.wconnect.workperformance.service.monthlyreport.IMonthlyReportService;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.ImmutableMap;
    import com.google.common.collect.Lists;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;

    import jakarta.validation.Valid;

    import java.text.MessageFormat;
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;

    /**
     * 月报控制器
     *
     * @author lichen
     * @date 2023/9/2
     */
    @RestController
    @RequestMapping("/monthly-report")
    public class MonthlyReportController {

        @Autowired
        private SessionContext sessionContext;
        @Autowired
        private IMonthlyReportService monthlyReportService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private ObjectMapper objectMapper;
        @Value("${file-max-size.import-report.monthly-report}")
        private long fileMaxSize;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;

        /**
         * 查询月报列表
         *
         * @param year     年
         * @param month    月
         * @param property 资产标识
         * @return java.util.List<cloud.wconnect.workperformance.pojo.vo.monthlyreport.MonthlyReportVO>
         * @author lichen
         * @date 2023/9/8
         */
        @ApiId(629)
        @GetMapping("/{year:\\d+}/{month:\\d+}")
        public List<MonthlyReportVO> list(@PathVariable int year, @PathVariable int month, String property) {
            int propertyId = sessionContext.getPropertyId(property);
            Integer tenantId = sessionContext.getTenantSymbolBO().getId();
            //查询月报列表
            List<MonthlyReport> monthlyReports = monthlyReportService.listByYearAndMonth(propertyId, year, month);
            //查询用户集合
            List<Integer> userIds = monthlyReports.stream().map(MonthlyReport::getCreateId).toList();
            Map<Integer, String> userId2Name = userInternalService.getNameMapByIds(tenantId, userIds);

            return beanMapper.mapList(monthlyReports, MonthlyReportVO.class, (entity, vo) -> {
                vo.setCreateName(userId2Name.get(entity.getCreateId()));
                //区域集合
                List<AreaVO> areaVOS = JsonUtils.convertStringToList(objectMapper, entity.getAreaIds(), Integer.class)
                        .stream().map(areaId -> new AreaVO(areaId, AreaEnum.getSort(areaId))).toList();
                vo.setAreaList(areaVOS);
            });
        }

        /**
         * 保存月报
         *
         * @param year     年
         * @param month    月
         * @param property 资产标识
         * @return 月报id
         * @author lichen
         * @date 2023/9/2
         */
        @ApiId(630)
        @PostMapping("/{year:\\d+}/{month:\\d+}")
        public Map<String, Long> save(@PathVariable int year, @PathVariable int month, String property) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            int loginUserId = sessionContext.getLoginUserId();
            //校验月报是否重复
            monthlyReportService.checkRepeat(propertyId, year, month);
            Long id = monthlyReportService.save(year, month, propertyDTO, loginUserId);
            return ImmutableMap.of("id", id);
        }

        /**
         * 报告导入
         *
         * @param property               资产标识
         * @param id                     月报id
         * @param file                   报告文件
         * @param monthlyReportImportDTO 导入dto
         * @return java.util.Map
         * @author lichen
         * @date 2023/9/6
         */
        @ApiId(632)
        @PutMapping("/{id:\\d+}")
        public Map importReport(String property, @PathVariable Long id, MultipartFile file,
                                @Valid MonthlyReportImportDTO monthlyReportImportDTO) {
            if (Objects.isNull(file)) {
                throw new BadRequestException(CommonErrorI18nConstant.CANNOT_EMPTY,
                        i18nMessageUtils.getErrorParamMapNeedTranslate(CommonFieldI18nConstant.FILE),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The file cannot be null");
            }
            // 校验文件格式
            UploadUtils.checkFileFormat(file, Lists.newArrayList("xls", "xlsx"));
            // 校验文件大小
            if (file.getSize() > fileMaxSize) {
                throw new BadRequestException(CommonErrorI18nConstant.FILE_SIZE_ERROR,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The fileSize max is " + fileMaxSize);
            }
            if (!SystemPlatformEnum.M3.getDesc().equals(monthlyReportImportDTO.getSystem())) {
                throw new BadRequestException(CommonErrorI18nConstant.MUST_IN_LIST,
                        i18nMessageUtils.getErrorParamMapNotNeedTranslate("system", "M3"),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        MessageFormat.format("The system name is invalid, systemName:{0}", monthlyReportImportDTO.getSystem()));
            }
            ReportTypeEnum.verifyValidity(monthlyReportImportDTO.getReportType());

            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            int loginUserId = sessionContext.getLoginUserId();
            MonthlyReport monthlyReport = monthlyReportService.checkExist(id);
            checkBelong(monthlyReport, propertyDTO.getId());

            monthlyReportService.importReport(propertyDTO, file, monthlyReportImportDTO, monthlyReport, loginUserId);
            return Collections.emptyMap();
        }

        /**
         * 校验月报是否归属于当前资产
         *
         * @param monthlyReport 月报
         * @param propertyId    资产id
         * @return void
         * @author lichen
         * @date 2023/9/6
         */
        private void checkBelong(MonthlyReport monthlyReport, Integer propertyId) {
            if (!monthlyReport.getPropertyId().equals(propertyId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(), BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(),
                        MessageFormat.format("The monthly report not belong to current property, monthlyReportId:{0}, currentPropertyId:{1}",
                                monthlyReport.getId(), propertyId));
            }
        }
    }