# SalesKpiWeeklyController.java

    package cloud.wconnect.workperformance.controller.saleskpi.weekly;

    import cloud.wconnect.commonlib.annotation.ApiId;
    import cloud.wconnect.commonlib.component.SessionContext;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.cons.CommonFieldI18nConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.pojo.dto.ListPagedDTO;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.workperformance.cons.saleskpi.SalesKpiErrorI18nConstant;
    import cloud.wconnect.workperformance.entity.saleskpi.SalesKpiWeekly;
    import cloud.wconnect.workperformance.pojo.dto.saleskpi.SalesKpiAttachmentDTO;
    import cloud.wconnect.workperformance.pojo.dto.saleskpi.weekly.SalesKpiWeeklyDTO;
    import cloud.wconnect.workperformance.pojo.dto.saleskpi.weekly.basic.SalesKpiWeeklyBasicDTO;
    import cloud.wconnect.workperformance.pojo.query.saleskpi.SalesKpiWeeklyQuery;
    import cloud.wconnect.workperformance.service.saleskpi.ISalesKpiFirstDayLogService;
    import cloud.wconnect.workperformance.service.saleskpi.ISalesKpiWeeklyAttachmentService;
    import cloud.wconnect.workperformance.service.saleskpi.ISalesKpiWeeklyService;
    import jakarta.annotation.Resource;
    import jakarta.validation.Valid;
    import org.springframework.web.bind.annotation.*;

    import java.time.LocalDate;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.temporal.ChronoField;
    import java.util.Collections;
    import java.util.LinkedHashMap;
    import java.util.Map;

    /**
     * <p>
     * sales kpi weekly 前端控制器
     * </p>
     *
     * @author zc
     * @since 2023-09-05
     */
    @RestController
    @RequestMapping("/sales-kpi/weekly")
    public class SalesKpiWeeklyController {

        @Resource
        private ISalesKpiFirstDayLogService salesKpiFirstDayLogService;
        @Resource
        private ISalesKpiWeeklyService salesKpiWeeklyService;
        @Resource
        private ISalesKpiWeeklyAttachmentService salesKpiWeeklyAttachmentService;
        @Resource
        private PropertyI18nRedisService propertyI18nRedisService;
        @Resource
        private SessionContext sessionContext;
        @Resource
        private I18nMessageUtils i18nMessageUtils;

        /**
         * 获取 Weekly 数据
         *
         * @param weekly   周（yyyyMMdd）
         * @param property 资产标识
         * @param query    查询条件
         * @return SalesKpiWeeklyDTO 集合
         * @author zc
         * @date 2023/9/9
         */
        @ApiId(644)
        @GetMapping("/{weekly}")
        public ListPagedDTO<SalesKpiWeeklyDTO> list(@PathVariable long weekly, String property, @Valid SalesKpiWeeklyQuery query) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            // 校验日期有效性
            checkDateFormat(weekly, propertyId, propertyDTO.getTimezone());
            return salesKpiWeeklyService.list(propertyDTO.getTenantId(), propertyId,
                    propertyDTO.getTimezone(), weekly, query);
        }

        /**
         * 保存 Weekly 数据
         *
         * @param id          数据 id
         * @param property    资产标识
         * @param weeklyBasic 保存内容
         * @return empty map
         * @author zc
         * @date 2023/9/11
         */
        @ApiId(645)
        @PutMapping("/{id:\\d+}")
        public Map<Object, Object> save(@PathVariable int id, String property, @RequestBody @Valid SalesKpiWeeklyBasicDTO weeklyBasic) {
            int propertyId = sessionContext.getPropertyId(property);
            // 校验数据是否存在
            SalesKpiWeekly originSalesKpiWeekly = salesKpiWeeklyService.checkExist(id);
            // 校验数据归属
            salesKpiWeeklyService.checkBelong(propertyId, originSalesKpiWeekly);
            // 保存数据
            salesKpiWeeklyService.save(id, originSalesKpiWeekly, weeklyBasic, sessionContext.getLoginUserId());
            return Collections.emptyMap();
        }

        /**
         * 保存 Weekly 附件
         *
         * @param weekly     周（yyyyMMdd）
         * @param property   资产标识
         * @param attachment 附件
         * @return empty map
         * @author zc
         * @date 2023/9/11
         */
        @ApiId(646)
        @PutMapping("/{weekly:\\d+}/attachment")
        public Map<Object, Object> saveAttachment(@PathVariable long weekly, String property,
                                                  @RequestBody @Valid SalesKpiAttachmentDTO attachment) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            // 校验日期有效性
            checkDateFormat(weekly, propertyId, propertyDTO.getTimezone());
            // 转换为 Weekly 所在周的周起始日
            long effectiveWeekly = salesKpiFirstDayLogService.conversionToFirstDayOfWeek(propertyId,
                    propertyDTO.getTimezone(), weekly);
            // 保存附件
            salesKpiWeeklyAttachmentService.saveAttachment(effectiveWeekly, propertyId,
                    sessionContext.getLoginUserId(), attachment.getUrl());
            return Collections.emptyMap();
        }

        /**
         * 获取 Weekly 附件
         *
         * @param weekly   周（yyyyMMdd）
         * @param property 资产标识
         * @return SalesKpiAttachmentDTO
         * @author zc
         * @date 2023/9/11
         */
        @ApiId(653)
        @GetMapping("/{weekly:\\d+}/attachment")
        public SalesKpiAttachmentDTO getAttachment(@PathVariable long weekly, String property) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            // 校验日期有效性
            checkDateFormat(weekly, propertyDTO.getId(), propertyDTO.getTimezone());
            // 转换为 Weekly 所在周的周起始日
            long effectiveWeekly = salesKpiFirstDayLogService.conversionToFirstDayOfWeek(propertyDTO.getId(),
                    propertyDTO.getTimezone(), weekly);
            return salesKpiWeeklyAttachmentService.getAttachment(propertyDTO.getTenantId(), propertyDTO.getId(), effectiveWeekly);
        }

        /**
         * 删除 Weekly 附件
         *
         * @param weekly   周（yyyyMMdd）
         * @param property 资产标识
         * @return empty map
         * @author zc
         * @date 2023/9/11
         */
        @ApiId(654)
        @DeleteMapping("/{weekly:\\d+}/attachment")
        public Map<Object, Object> deleteAttachment(@PathVariable long weekly, String property) {
            int propertyId = sessionContext.getPropertyId(property);
            PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
            // 校验日期有效性
            checkDateFormat(weekly, propertyDTO.getId(), propertyDTO.getTimezone());
            // 转换为 Weekly 所在周的周起始日
            long effectiveWeekly = salesKpiFirstDayLogService.conversionToFirstDayOfWeek(propertyDTO.getId(),
                    propertyDTO.getTimezone(), weekly);
            // 删除附件
            salesKpiWeeklyAttachmentService.deleteAttachment(effectiveWeekly, propertyDTO.getId());
            return Collections.emptyMap();
        }

        /**
         * 校验日期有效性
         *
         * @param weekly     周（yyyyMMdd）
         * @param propertyId 资产 id
         * @param timezone   时区
         * @author zc
         * @date 2023/9/9
         */
        private void checkDateFormat(long weekly, int propertyId, String timezone) {
            LocalDate localDate;
            try {
                localDate = DateTimeUtils.strToLocalDate(String.valueOf(weekly), BaseConstant.DATE_FORMAT_YYYYMMDD);
            } catch (Exception e) {
                LinkedHashMap<String, Boolean> map = new LinkedHashMap<>();
                map.put(CommonFieldI18nConstant.WEEK, true);
                map.put(BaseConstant.DATE_FORMAT_YYYYMMDD,false);
                throw new BadRequestException(CommonErrorI18nConstant.FORMAT_ERROR,
                        i18nMessageUtils.getErrorParamMap(map),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The weekly param is wrong format.");
            }

            ZonedDateTime currentDate = DateTimeUtils.dateNow(timezone);
            int firstDayOfWeek = salesKpiFirstDayLogService.getFirstDay(propertyId);
            // 获取当前时间的周起始日
            ZonedDateTime currentDayOfWeek = (currentDate.getDayOfWeek().getValue() >= firstDayOfWeek) ?
                    currentDate.with(ChronoField.DAY_OF_WEEK, firstDayOfWeek) :
                    currentDate.minusWeeks(1).with(ChronoField.DAY_OF_WEEK, firstDayOfWeek);

            // 只能查看历史周期数据，目标日期 < 当前时间的周起始日
            if (!localDate.atStartOfDay(ZoneId.of(timezone)).isBefore(currentDayOfWeek)) {
                throw new BadRequestException(SalesKpiErrorI18nConstant.CANNOT_OPERATE_FEATURE,
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "Cannot operate feature data.");
            }
        }
    }