# SalesKpiMonthlyInternalController.java

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

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.controller.BaseInternalController;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.service.PropertyInternalService;
    import cloud.wconnect.commonlib.util.InternationalizationUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.workperformance.cons.saleskpi.SalesKpiMonthlyDataSourceCons;
    import cloud.wconnect.workperformance.pojo.dto.saleskpi.monthly.SalesKpiSalesItemDataDTO;
    import cloud.wconnect.workperformance.pojo.dto.saleskpi.monthly.SalesKpiSalesItemReportDTO;
    import cloud.wconnect.workperformance.pojo.dto.saleskpi.monthly.SalesKpiSalesmanItemDTO;
    import cloud.wconnect.workperformance.service.saleskpi.ISalesKpiMonthlyService;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.Lists;
    import jakarta.annotation.Resource;
    import jakarta.validation.Valid;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.*;

    import java.math.BigDecimal;
    import java.math.RoundingMode;
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;

    /**
     * Controller：Sales KPI Monthly Internal
     *
     * @author zc
     * @date 2023/09/11
     */
    @Slf4j
    @RestController
    @RequestMapping("/internal/sales-kpi/monthly")
    public class SalesKpiMonthlyInternalController extends BaseInternalController {

        @Resource
        private ISalesKpiMonthlyService salesKpiMonthlyService;
        @Resource
        private PropertyInternalService propertyInternalService;
        @Resource
        private ObjectMapper objectMapper;

        @Value("${internal.service.auth-key.basic}")
        private String authKey;

        /**
         * 上报销售指标数据
         *
         * @param monthly          月份（yyyyMM）
         * @param tenant           租户标识
         * @param property         资产标识
         * @param salesItemDataDTO 指标数据
         * @param sign             签名
         * @return empty map
         * @author zc
         * @date 2023/9/11
         */
        @PostMapping("/{monthly:\\d+}/sales-data")
        public Map<Object, Object> saveSalesData(@PathVariable long monthly, String tenant, String property,
                                                 @RequestBody @Valid SalesKpiSalesItemDataDTO salesItemDataDTO,
                                                 @RequestHeader String sign) {
            log.info("Sales KPI Monthly internal - Save sales data start, tenant:{}, property:{}, dataJson:{}",
                    tenant, property, JsonUtils.convertObjToString(objectMapper, salesItemDataDTO));

            List<String> effectiveDataSources = Lists.newArrayList(
                    SalesKpiMonthlyDataSourceCons.DATA_SOURCE_GROUPS_MEETING_DEFINITE_ROOM_REVENUE,
                    SalesKpiMonthlyDataSourceCons.DATA_SOURCE_GROUPS_MEETING_RESPONSE_RATE,
                    SalesKpiMonthlyDataSourceCons.DATA_SOURCE_GROUPS_MEETING_RESPONSE_TIME,
                    SalesKpiMonthlyDataSourceCons.DATA_SOURCE_GROUPS_MEETING_TURN_DOWN,
                    SalesKpiMonthlyDataSourceCons.DATA_SOURCE_GROUPS_MEETING_CONVERSION,
                    SalesKpiMonthlyDataSourceCons.DATA_SOURCE_REVPAR);
            if (!effectiveDataSources.contains(salesItemDataDTO.getDataSource())) {
                log.error("Sales KPI Monthly internal - Save sales data error, the dataSource param is error." +
                        " tenant:{}, property:{}, dataSource:{}", tenant, property, salesItemDataDTO.getDataSource());

                throw new BadRequestException(BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getI18nCode(),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The dataSource param is error. dataSource:" + salesItemDataDTO.getDataSource());
            }

            // 校验签名
            checkIntranetParams(authKey, sign, monthly, tenant, property);

            PropertyDTO propertyDTO = propertyInternalService.getOne(property, tenant);
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(propertyDTO
                    .getInternationalization().getNumber().getCalculationRule());
            if (Objects.nonNull(salesItemDataDTO.getValue())) {
                salesItemDataDTO.setValue(salesItemDataDTO.getValue().setScale(BaseConstant.DATA_PRECISION, roundingMode));
            }

            // 保存销售指标数据
            salesKpiMonthlyService.saveSalesData(propertyDTO.getId(), monthly, salesItemDataDTO.getDataSource(),
                    salesItemDataDTO.getValue(), salesItemDataDTO.getReportUrl());

            log.info("Sales KPI Monthly internal - Save sales data end, tenant:{}, property:{}", tenant, property);

            return Collections.emptyMap();
        }

        /**
         * 上报业务员指标数据
         *
         * @param monthly         月份（yyyyMM）
         * @param tenant          租户标识
         * @param property        资产标识
         * @param salesmanItemDTO 指标数据
         * @param sign            签名
         * @return empty map
         * @author zc
         * @date 2023/9/11
         */
        @PostMapping("/{monthly:\\d+}/salesman-data")
        public Map<Object, Object> saveSalesmanData(@PathVariable long monthly, String tenant, String property,
                                                    @RequestBody @Valid SalesKpiSalesmanItemDTO salesmanItemDTO,
                                                    @RequestHeader String sign) {
            log.info("Sales KPI Monthly internal - Save salesman data start, tenant:{}, property:{}, dataJson:{}",
                    tenant, property, JsonUtils.convertObjToString(objectMapper, salesmanItemDTO));

            List<String> effectiveDataSources = Lists.newArrayList(
                    SalesKpiMonthlyDataSourceCons.DATA_SOURCE_MONTHLY_ACTIVITIES,
                    SalesKpiMonthlyDataSourceCons.DATA_SOURCE_FUTURE_PROSPECT,
                    SalesKpiMonthlyDataSourceCons.DATA_SOURCE_FUTURE_TENTATIVE,
                    SalesKpiMonthlyDataSourceCons.DATA_SOURCE_FUTURE_DEFINITE,
                    SalesKpiMonthlyDataSourceCons.DATA_SOURCE_FUTURE_CATERING_PACE);
            if (!effectiveDataSources.contains(salesmanItemDTO.getDataSource())) {
                log.error("Sales KPI Monthly internal - Save salesman data error, the dataSource param is error." +
                        " tenant:{}, property:{}, dataSource:{}", tenant, property, salesmanItemDTO.getDataSource());

                throw new BadRequestException(BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getI18nCode(),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The dataSource param is error. dataSource:" + salesmanItemDTO.getDataSource());
            }

            // 校验签名
            checkIntranetParams(authKey, sign, monthly, tenant, property);

            PropertyDTO propertyDTO = propertyInternalService.getOne(property, tenant);
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(propertyDTO
                    .getInternationalization().getNumber().getCalculationRule());
            salesmanItemDTO.getData().forEach(item -> {
                if (Objects.nonNull(item.getValue1())) {
                    item.setValue1(item.getValue1().setScale(BaseConstant.DATA_PRECISION, roundingMode));
                }
                if (Objects.nonNull(item.getValue2())) {
                    item.setValue2(item.getValue2().setScale(BaseConstant.DATA_PRECISION, roundingMode));
                }
            });

            // 保存业务员指标数据
            salesKpiMonthlyService.saveSalesmanData(propertyDTO.getId(), monthly, salesmanItemDTO.getDataSource(),
                    salesmanItemDTO.getData());

            log.info("Sales KPI Monthly internal - Save salesman data end, tenant:{}, property:{}", tenant, property);

            return Collections.emptyMap();
        }

        /**
         * 上报采集文件
         *
         * @param monthly       月份（yyyyMM）
         * @param tenant        租户标识
         * @param property      资产标识
         * @param itemReportDTO 文件指标数据
         * @param sign          签名
         * @return empty map
         * @author zc
         * @date 2023/9/11
         */
        @PostMapping("/{monthly:\\d+}/report")
        public Map<Object, Object> saveReport(@PathVariable long monthly, String tenant, String property,
                                              @RequestBody @Valid SalesKpiSalesItemReportDTO itemReportDTO,
                                              @RequestHeader String sign) {
            log.info("Sales KPI Monthly internal - Save report start, tenant:{}, property:{}, dataJson:{}",
                    tenant, property, JsonUtils.convertObjToString(objectMapper, itemReportDTO));

            if (!SalesKpiMonthlyDataSourceCons.DATA_SOURCE_REVPAR.equals(itemReportDTO.getDataSource())) {
                log.error("Sales KPI Monthly internal - Save report error, the dataSource param is error." +
                        " tenant:{}, property:{}, dataSource:{}", tenant, property, itemReportDTO.getDataSource());

                throw new BadRequestException(BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getI18nCode(),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                        "The dataSource param is error. dataSource:" + itemReportDTO.getDataSource());
            }

            // 校验签名
            checkIntranetParams(authKey, sign, monthly, tenant, property);

            PropertyDTO propertyDTO = propertyInternalService.getOne(property, tenant);
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(propertyDTO
                    .getInternationalization().getNumber().getCalculationRule());
            // 提取报告指标数据
            BigDecimal value = salesKpiMonthlyService.getReportItemValue(propertyDTO, itemReportDTO.getReportUrl());

            // 保存业务员指标数据
            salesKpiMonthlyService.saveSalesData(propertyDTO.getId(), monthly, itemReportDTO.getDataSource(),
                    Objects.nonNull(value) ? value.setScale(BaseConstant.DATA_PRECISION, roundingMode) : null, null);

            log.info("Sales KPI Monthly internal - Save report end, tenant:{}, property:{}", tenant, property);

            return Collections.emptyMap();
        }
    }