| @@ -0,0 +1,35 @@ | |||||
| package com.iformall.controller.datatower; | |||||
| import com.iformall.annotation.TenantIgnore; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.controller.base.BaseController; | |||||
| import com.iformall.service.CockpitScreenService; | |||||
| import io.swagger.annotations.Api; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| @Api(description = "驾驶舱大屏") | |||||
| @RestController | |||||
| @RequestMapping("cockpitscreen") | |||||
| public class CockpitScreenController extends BaseController { | |||||
| @Autowired | |||||
| private CockpitScreenService cockpitScreenService; | |||||
| @TenantIgnore | |||||
| @ApiOperation("驾驶舱大屏-统计会员性别") | |||||
| @GetMapping("/countUserGender") | |||||
| public ResultData countUserGender() { | |||||
| return new ResultData(cockpitScreenService.countUserGender(getTenantInfo())); | |||||
| } | |||||
| @TenantIgnore | |||||
| @ApiOperation("驾驶舱大屏-统计商铺") | |||||
| @GetMapping("/countShop") | |||||
| public ResultData countShop() { | |||||
| return new ResultData(cockpitScreenService.countShop(getTenantInfo())); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| package com.iformall.common; | |||||
| /** | |||||
| * 公用常量 | |||||
| * | |||||
| * @author xmzhao71 | |||||
| * @date 2023-09-20 | |||||
| */ | |||||
| public interface CommonConstant { | |||||
| /** | |||||
| * 保留小数位(符合语义的使用) | |||||
| */ | |||||
| int SCALE_2 = 2; | |||||
| int SCALE_3 = 3; | |||||
| int SCALE_4 = 4; | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| package com.iformall.domain.dto.cockpit; | |||||
| import com.iformall.domain.vo.cockpit.CountShopVO; | |||||
| import io.swagger.annotations.ApiModel; | |||||
| import io.swagger.annotations.ApiModelProperty; | |||||
| import lombok.Data; | |||||
| @ApiModel(value = "根据状态统计商铺数量") | |||||
| @Data | |||||
| public class CountShopByStatusDTO { | |||||
| @ApiModelProperty(value = "商铺状态") | |||||
| private Integer status; | |||||
| @ApiModelProperty(value = "商铺数量") | |||||
| private Integer shopCount; | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| package com.iformall.domain.dto.cockpit; | |||||
| import com.iformall.domain.vo.cockpit.CountUserGenderVO; | |||||
| import io.swagger.annotations.ApiModel; | |||||
| import io.swagger.annotations.ApiModelProperty; | |||||
| import lombok.AllArgsConstructor; | |||||
| import lombok.Data; | |||||
| import lombok.NoArgsConstructor; | |||||
| @ApiModel(value = "根据性别统计会员数量") | |||||
| @Data | |||||
| @NoArgsConstructor | |||||
| @AllArgsConstructor | |||||
| public class CountUserByGenderDTO { | |||||
| @ApiModelProperty(value = "用户性别") | |||||
| private Integer gender; | |||||
| @ApiModelProperty(value = "用户数量") | |||||
| private Integer userCount; | |||||
| public static CountUserGenderVO.CountUserGenderDetailVO mapping(CountUserByGenderDTO dto) { | |||||
| CountUserGenderVO.CountUserGenderDetailVO vo = new CountUserGenderVO.CountUserGenderDetailVO(); | |||||
| vo.setGender(dto.getGender()); | |||||
| vo.setUserCount(dto.getUserCount()); | |||||
| return vo; | |||||
| } | |||||
| private static String acquireGender(Integer gender) { | |||||
| switch (gender) { | |||||
| case 1: | |||||
| return "男"; | |||||
| case 2: | |||||
| return "女"; | |||||
| default: | |||||
| return "不详"; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,22 @@ | |||||
| package com.iformall.domain.vo.cockpit; | |||||
| import io.swagger.annotations.ApiModel; | |||||
| import io.swagger.annotations.ApiModelProperty; | |||||
| import lombok.Data; | |||||
| import java.math.BigDecimal; | |||||
| @ApiModel(value = "商铺统计返回数据") | |||||
| @Data | |||||
| public class CountShopVO { | |||||
| @ApiModelProperty(value = "总的商铺数量") | |||||
| private Integer totalShopCount; | |||||
| @ApiModelProperty(value = "出租的商铺数量") | |||||
| private Integer rentedShopCount; | |||||
| @ApiModelProperty(value = "出租的商铺数量比例") | |||||
| private BigDecimal rentedShopCountRatio; | |||||
| @ApiModelProperty(value = "未出租的商铺数量") | |||||
| private Integer unRentedShopCount; | |||||
| @ApiModelProperty(value = "未出租的商铺数量比例") | |||||
| private BigDecimal unRentedShopCountRatio; | |||||
| } | |||||
| @@ -0,0 +1,29 @@ | |||||
| package com.iformall.domain.vo.cockpit; | |||||
| import io.swagger.annotations.ApiModel; | |||||
| import io.swagger.annotations.ApiModelProperty; | |||||
| import lombok.Data; | |||||
| import java.math.BigDecimal; | |||||
| import java.util.List; | |||||
| @ApiModel(value = "会员性别统计返回数据") | |||||
| @Data | |||||
| public class CountUserGenderVO { | |||||
| @ApiModelProperty(value = "总的会员数量") | |||||
| private Integer totalUserCount; | |||||
| @ApiModelProperty(value = "会员数量详情") | |||||
| private List<CountUserGenderDetailVO> userGenderDetails; | |||||
| @ApiModel(value = "会员性别统计详情返回数据") | |||||
| @Data | |||||
| public static class CountUserGenderDetailVO { | |||||
| @ApiModelProperty(value = "性别:0:不详 1:男 2:女") | |||||
| private Integer gender; | |||||
| @ApiModelProperty(value = "每个性别的数量") | |||||
| private Integer userCount; | |||||
| @ApiModelProperty(value = "每个性别的比例") | |||||
| private BigDecimal userCountRatio; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,40 @@ | |||||
| package com.iformall.enums; | |||||
| /** | |||||
| * 用户性别枚举 | |||||
| * | |||||
| * @author xmzhao71 | |||||
| * @date 2023-09-20 | |||||
| */ | |||||
| public enum EnumUserGender { | |||||
| GENDER_UNKNOWN(0, "不详"), | |||||
| GENDER_MALE(1, "男"), | |||||
| GENDER_FEMALE(2, "女"), | |||||
| ; | |||||
| public static EnumUserGender getEnum(Integer code) { | |||||
| for (EnumUserGender value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String desc; | |||||
| EnumUserGender(Integer code, String desc) { | |||||
| this.code = code; | |||||
| this.desc = desc; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getDesc() { | |||||
| return desc; | |||||
| } | |||||
| } | |||||
| @@ -2,10 +2,12 @@ package com.iformall.mapper; | |||||
| import com.iformall.common.CommonMapper; | import com.iformall.common.CommonMapper; | ||||
| import com.iformall.domain.dto.WxCUserBasicInfoDto; | import com.iformall.domain.dto.WxCUserBasicInfoDto; | ||||
| import com.iformall.domain.dto.cockpit.CountUserByGenderDTO; | |||||
| import com.iformall.domain.po.WxCUserBasicInfo; | import com.iformall.domain.po.WxCUserBasicInfo; | ||||
| import com.iformall.domain.vo.CUserBaseVo; | import com.iformall.domain.vo.CUserBaseVo; | ||||
| import com.iformall.domain.vo.UserCountVo; | import com.iformall.domain.vo.UserCountVo; | ||||
| import com.iformall.domain.vo.WxCUserBasicInfoVo; | import com.iformall.domain.vo.WxCUserBasicInfoVo; | ||||
| import com.iformall.domain.vo.cockpit.CountUserGenderVO; | |||||
| import org.apache.ibatis.annotations.Param; | import org.apache.ibatis.annotations.Param; | ||||
| import java.util.List; | import java.util.List; | ||||
| @@ -64,5 +66,12 @@ public interface WxCUserBasicInfoMapper extends CommonMapper<WxCUserBasicInfo, S | |||||
| List<Long> findIdByFilter(WxCUserBasicInfoDto wxCUserBasicInfoDto); | List<Long> findIdByFilter(WxCUserBasicInfoDto wxCUserBasicInfoDto); | ||||
| long getTotalCreditAmount(@Param("tenantId")String tenantId, @Param("finalTenantId")String finalTenantId); | long getTotalCreditAmount(@Param("tenantId")String tenantId, @Param("finalTenantId")String finalTenantId); | ||||
| /** | |||||
| * 通过性别统计用户 | |||||
| * | |||||
| * @param finalTenantId | |||||
| */ | |||||
| List<CountUserByGenderDTO> countUserByGender(@Param("finalTenantId") String finalTenantId); | |||||
| } | } | ||||
| @@ -1,6 +1,7 @@ | |||||
| package com.iformall.mapper; | package com.iformall.mapper; | ||||
| import com.iformall.common.CommonMapper; | import com.iformall.common.CommonMapper; | ||||
| import com.iformall.domain.dto.cockpit.CountShopByStatusDTO; | |||||
| import com.iformall.domain.po.WxShop; | import com.iformall.domain.po.WxShop; | ||||
| import com.iformall.domain.vo.WxShopVo; | import com.iformall.domain.vo.WxShopVo; | ||||
| import org.apache.ibatis.annotations.Param; | import org.apache.ibatis.annotations.Param; | ||||
| @@ -47,4 +48,6 @@ public interface WxShopMapper extends CommonMapper<WxShop, String> { | |||||
| List<WxShopVo> newFindShopVoList(@Param("tenantId")String tenantId, @Param("shopIds")List<Long> shopIds); | List<WxShopVo> newFindShopVoList(@Param("tenantId")String tenantId, @Param("shopIds")List<Long> shopIds); | ||||
| long findCount(WxShop wxShop); | long findCount(WxShop wxShop); | ||||
| List<CountShopByStatusDTO> countShopByStatus(@Param("tenantIds") List<String> tenantIds); | |||||
| } | } | ||||
| @@ -0,0 +1,17 @@ | |||||
| package com.iformall.service; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import com.iformall.domain.vo.cockpit.CountShopVO; | |||||
| import com.iformall.domain.vo.cockpit.CountUserGenderVO; | |||||
| /** | |||||
| * 驾驶舱大屏服务 | |||||
| * | |||||
| * @author xmzhao71 | |||||
| * @date 2023-09-20 | |||||
| */ | |||||
| public interface CockpitScreenService { | |||||
| CountUserGenderVO countUserGender(TenantEntity tenantInfo); | |||||
| CountShopVO countShop(TenantEntity tenantInfo); | |||||
| } | |||||
| @@ -0,0 +1,99 @@ | |||||
| package com.iformall.service.impl; | |||||
| import com.iformall.common.CommonConstant; | |||||
| import com.iformall.domain.dto.cockpit.CountShopByStatusDTO; | |||||
| import com.iformall.domain.dto.cockpit.CountUserByGenderDTO; | |||||
| import com.iformall.domain.po.base.TenantEntity; | |||||
| import com.iformall.domain.vo.cockpit.CountShopVO; | |||||
| import com.iformall.domain.vo.cockpit.CountUserGenderVO; | |||||
| import com.iformall.enums.EnumShopStatus; | |||||
| import com.iformall.enums.EnumUserGender; | |||||
| import com.iformall.mapper.WxCUserBasicInfoMapper; | |||||
| import com.iformall.mapper.WxShopMapper; | |||||
| import com.iformall.service.CockpitScreenService; | |||||
| import com.iformall.service.WxCUserBasicInfoService; | |||||
| import com.iformall.service.WxMallService; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import java.math.BigDecimal; | |||||
| import java.math.RoundingMode; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import java.util.stream.Collectors; | |||||
| /** | |||||
| * 驾驶舱大屏服务 | |||||
| * | |||||
| * @author xmzhao71 | |||||
| * @date 2023-09-20 | |||||
| */ | |||||
| @Service | |||||
| public class CockpitScreenServiceImpl implements CockpitScreenService { | |||||
| @Autowired | |||||
| private WxCUserBasicInfoService cUserBasicInfoService; | |||||
| @Autowired | |||||
| private WxCUserBasicInfoMapper cUserBasicInfoMapper; | |||||
| @Autowired | |||||
| private WxMallService wxMallService; | |||||
| @Autowired | |||||
| private WxShopMapper wxShopMapper; | |||||
| @Override | |||||
| public CountUserGenderVO countUserGender(TenantEntity tenantEntity) { | |||||
| CountUserGenderVO result = new CountUserGenderVO(); | |||||
| List<CountUserByGenderDTO> dtos = cUserBasicInfoMapper.countUserByGender(tenantEntity.getFinalTenantId()); | |||||
| List<CountUserByGenderDTO> totalGenders = dtos.stream().filter(x -> | |||||
| x.getGender() != null && (x.getGender().equals(EnumUserGender.GENDER_MALE.getCode()) || x.getGender().equals(EnumUserGender.GENDER_FEMALE.getCode())) | |||||
| ).collect(Collectors.toList()); | |||||
| Integer unknownGender = dtos.stream().filter(x -> | |||||
| x.getGender() == null || x.getGender().equals(EnumUserGender.GENDER_UNKNOWN.getCode()) | |||||
| ).map(CountUserByGenderDTO::getUserCount).reduce(Integer::sum).orElse(0); | |||||
| totalGenders.add(new CountUserByGenderDTO(EnumUserGender.GENDER_UNKNOWN.getCode(), unknownGender)); | |||||
| Integer totalUserCount = totalGenders.stream().map(CountUserByGenderDTO::getUserCount).reduce(Integer::sum).orElse(0); | |||||
| result.setTotalUserCount(totalUserCount); | |||||
| List<CountUserGenderVO.CountUserGenderDetailVO> vos = totalGenders.stream().map(x -> { | |||||
| CountUserGenderVO.CountUserGenderDetailVO vo = CountUserByGenderDTO.mapping(x); | |||||
| BigDecimal userCountRatio = BigDecimal.valueOf(x.getUserCount()).divide(BigDecimal.valueOf(totalUserCount), CommonConstant.SCALE_4, RoundingMode.HALF_UP); | |||||
| vo.setUserCountRatio(userCountRatio); | |||||
| return vo; | |||||
| }).collect(Collectors.toList()); | |||||
| BigDecimal genderRatio = vos.stream().filter(x -> !EnumUserGender.GENDER_UNKNOWN.getCode().equals(x.getGender())).map(CountUserGenderVO.CountUserGenderDetailVO::getUserCountRatio).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); | |||||
| vos = vos.stream().map(x -> { | |||||
| if (EnumUserGender.GENDER_UNKNOWN.getCode().equals(x.getGender())) { | |||||
| x.setUserCountRatio(BigDecimal.ONE.subtract(genderRatio)); | |||||
| } | |||||
| return x; | |||||
| }).collect(Collectors.toList()); | |||||
| result.setUserGenderDetails(vos); | |||||
| return result; | |||||
| } | |||||
| @Override | |||||
| public CountShopVO countShop(TenantEntity tenantInfo) { | |||||
| CountShopVO result = new CountShopVO(); | |||||
| List<TenantEntity> tenantInfos = wxMallService.getTenantEntitys(tenantInfo); | |||||
| List<String> tenantIds = tenantInfos.stream().map(TenantEntity::getTenantId).collect(Collectors.toList()); | |||||
| List<CountShopByStatusDTO> dtos = wxShopMapper.countShopByStatus(tenantIds); | |||||
| Map<Integer, Integer> shopMap = dtos.stream().collect(Collectors.toMap(CountShopByStatusDTO::getStatus, CountShopByStatusDTO::getShopCount)); | |||||
| Integer totalShopCount = dtos.stream().map(CountShopByStatusDTO::getShopCount).reduce(Integer::sum).orElse(0); | |||||
| result.setTotalShopCount(totalShopCount); | |||||
| Integer rentedShopCount = shopMap.get(EnumShopStatus.RENT.getCode()); | |||||
| Integer unRentedShopCount = shopMap.get(EnumShopStatus.NOT_RENT.getCode()); | |||||
| result.setRentedShopCount(rentedShopCount); | |||||
| result.setUnRentedShopCount(unRentedShopCount); | |||||
| BigDecimal rentedShopCountRatio = BigDecimal.valueOf(rentedShopCount).divide(BigDecimal.valueOf(totalShopCount), CommonConstant.SCALE_4, RoundingMode.HALF_UP); | |||||
| result.setRentedShopCountRatio(rentedShopCountRatio); | |||||
| result.setUnRentedShopCountRatio(BigDecimal.ONE.subtract(rentedShopCountRatio)); | |||||
| return result; | |||||
| } | |||||
| } | |||||
| @@ -570,6 +570,12 @@ | |||||
| and wcubi.`tenant_id` like concat('%,', #{tenantId},',%') | and wcubi.`tenant_id` like concat('%,', #{tenantId},',%') | ||||
| </if> | </if> | ||||
| </select> | </select> | ||||
| <select id="countUserByGender" resultType="com.iformall.domain.dto.cockpit.CountUserByGenderDTO"> | |||||
| SELECT sex AS gender, COUNT(id) AS userCount | |||||
| FROM wx_c_user_basic_info | |||||
| WHERE final_tenant_id = #{finalTenantId} | |||||
| GROUP BY sex; | |||||
| </select> | |||||
| <update id="incActRecordById" parameterType="java.util.HashMap"> | <update id="incActRecordById" parameterType="java.util.HashMap"> | ||||
| @@ -619,4 +619,17 @@ | |||||
| </foreach> | </foreach> | ||||
| </if> | </if> | ||||
| </select> | </select> | ||||
| <select id="countShopByStatus" resultType="com.iformall.domain.dto.cockpit.CountShopByStatusDTO"> | |||||
| SELECT `status` AS status, COUNT(id) AS shopCount | |||||
| FROM wx_shop | |||||
| WHERE | |||||
| <if test="null != tenantIds and tenantIds.size() > 0"> | |||||
| tenant_id in | |||||
| <foreach collection="tenantIds" index="index" item="tenantId" open="(" separator="," close=")"> | |||||
| #{tenantId} | |||||
| </foreach> | |||||
| </if> | |||||
| GROUP BY `status`; | |||||
| </select> | |||||
| </mapper> | </mapper> | ||||