Переглянути джерело

feat:获取公募基金的基金经理信息的实现

mozuwen 1 рік тому
батько
коміт
5c33212253

+ 79 - 0
src/main/java/com/smppw/analysis/application/service/info/FundInfoService.java

@@ -461,4 +461,83 @@ public class FundInfoService {
         result.put(benchmarkId, valueBenchmarkMap);
         return result;
     }
+
+    public List<ManualFundManagerInfoVO> managerList(ManualFundManagerParams params) {
+        String refId = params.getRefId();
+        String benchmarkId = params.getBenchmarkId();
+        List<ManualFundManagerInfoVO> resultList = ListUtil.list(true);
+       //1.先获取基金下的现任基金经理基本信息
+        List<PersonnelInformationDo> managerInfoList = this.baseInfoService.getFundPresentManagerInfo(refId);
+        if(CollUtil.isEmpty(managerInfoList)){
+            return resultList;
+        }
+        List<String> managerIdList = managerInfoList.stream().map(PersonnelInformationDo::getPersonnelId).collect(Collectors.toList());
+        //2.获取现任基金经理管理的产品
+        List<MfManagerFundNumDo> mfManagerFundNumList = this.baseInfoService.listMfManagerFundNumByManagerId(managerIdList);
+        Map<String, List<MfManagerFundNumDo>> listMap = mfManagerFundNumList.stream().collect(Collectors.groupingBy(MfManagerFundNumDo::getManagerId));
+        //3.不改变以前的处理逻辑,将PersonnelInformationDo转化为ManualFundManagerInfoDo
+        List<ManualFundManagerInfoDo> dataList = managerInfoList.stream().map(e -> {
+            ManualFundManagerInfoDo manualFundManagerInfoDo = new ManualFundManagerInfoDo();
+            String managerId = e.getPersonnelId();
+            manualFundManagerInfoDo.setManagerId(managerId);
+            manualFundManagerInfoDo.setManagerName(e.getPersonnelName());
+            manualFundManagerInfoDo.setAvatar(e.getAvatar());
+            manualFundManagerInfoDo.setAvatar2(e.getAvatar2());
+            List<MfManagerFundNumDo> mfManagerFundNumDos = listMap.get(managerId);
+            if (CollUtil.isNotEmpty(mfManagerFundNumDos)) {
+                MfManagerFundNumDo mfManagerFundNumDo = mfManagerFundNumDos.stream().filter(k -> refId.equals(k.getFundId())).findFirst().orElse(null);
+                if (manualFundManagerInfoDo != null) {
+                    manualFundManagerInfoDo.setStartDate(mfManagerFundNumDo.getStartDate());
+                }
+                long publicProductNumAll = mfManagerFundNumDos.stream().filter(v -> v.getFundId().startsWith("MF")).count();
+                long publicProductNumRunning = mfManagerFundNumDos.stream().filter(w -> Objects.equals(2, w.getStatus()) && w.getEndDate()==null).count();
+                manualFundManagerInfoDo.setPublicProductNumAll(String.valueOf(publicProductNumAll));
+                manualFundManagerInfoDo.setPublicProductNumRunning(String.valueOf(publicProductNumRunning));
+            }
+            return manualFundManagerInfoDo;
+        }).collect(Collectors.toList());
+        dataList = dataList.stream().filter(e -> e.getStartDate() != null).collect(Collectors.toList());
+        // 按基金经理分组每个经理只取一条数据
+        Map<String, ManualFundManagerInfoDo> managerInfoMap = MapUtil.newHashMap();
+        Map<String, List<ManualFundManagerInfoDo>> collect = dataList.stream().collect(Collectors.groupingBy(ManualFundManagerInfoDo::getManagerId, Collectors.toList()));
+        collect.forEach((k ,v) -> {
+            ManualFundManagerInfoDo temp = v.stream().findFirst().orElse(null);
+            managerInfoMap.put(k, temp);
+        });
+        List<Indicator> indicatorList = ListUtil.of(Indicator.IntervalReturn, Indicator.AnnualReturn, Indicator.SharpeRatio);
+        managerInfoMap.forEach((k, data) -> {
+            ManualFundManagerInfoVO vo = new ManualFundManagerInfoVO();
+            vo.setManagerId(data.getManagerId());
+            vo.setManagerName(data.getManagerName());
+            vo.setAvatar(data.getAvatar());
+            vo.setAvatar2(data.getAvatar2());
+            vo.setGender(data.getGenderValue());
+            vo.setFundNum(data.getPublicProductNumAll());
+            vo.setRunningNum(data.getPublicProductNumRunning());
+            // 取经理的所有在管基金的最新资产值并求和
+            List<ManualFundAssetSizeDo> tempList = this.baseInfoService.getAssetSizeList(data.getManagerId());
+            if (CollUtil.isNotEmpty(tempList)) {
+                List<String> fundIds = tempList.stream().map(ManualFundAssetSizeDo::getFundId).distinct().collect(Collectors.toList());
+                Double total = 0d;
+                for (String fundId : fundIds) {
+                    Double aDouble = tempList.stream().filter(e -> e.getFundId().equals(fundId)).max(Comparator.comparing(ManualFundAssetSizeDo::getDate))
+                            .map(ManualFundAssetSizeDo::getFundAssetSize).orElse(0d);
+                    total += aDouble;
+                }
+                vo.setRunningScale(String.valueOf(total));
+            }
+            // 指标计算结果处理
+            Map<String, Map<String, String>> indicatorValue = this.getIndicatorValue(refId, benchmarkId, data.getStartDate(), data.getEndDate(), indicatorList);
+            if (indicatorValue.get(refId) != null) {
+                vo.setNavChange(indicatorValue.get(refId).get(Indicator.IntervalReturn.name()));
+                vo.setAnnualRet(indicatorValue.get(refId).get(Indicator.AnnualReturn.name()));
+                vo.setSharpe(indicatorValue.get(refId).get(Indicator.SharpeRatio.name()));
+            }
+            if (indicatorValue.get(benchmarkId) != null) {
+                vo.setBenchmarkRet(indicatorValue.get(benchmarkId).get(Indicator.IntervalReturn.name()));
+            }
+            resultList.add(vo);
+        });
+        return resultList;
+    }
 }

+ 11 - 0
src/main/java/com/smppw/analysis/client/FundApi.java

@@ -129,6 +129,17 @@ public class FundApi {
     }
 
     /**
+     * 公募基金详情页-基金经理
+     *
+     * @param params 基金id
+     * @return 基金经理信息
+     */
+    @GetMapping("mf-manager-info")
+    public ResultVo<List<ManualFundManagerInfoVO>> managerInfo(ManualFundManagerParams params) {
+        return ResultVo.ok(this.service.managerList(params));
+    }
+
+    /**
      * 公募基金的基金经理变更历史
      *
      * @param params 基金id

+ 6 - 0
src/main/java/com/smppw/analysis/domain/dao/FundInformationDao.java

@@ -8,6 +8,7 @@ import com.smppw.analysis.domain.mapper.core.FundInformationDoMapper;
 import com.smppw.analysis.domain.mapper.core.MonetaryFundProfitMapper;
 import com.smppw.common.pojo.enums.Frequency;
 import com.smppw.common.pojo.enums.Indicator;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.stereotype.Component;
 
 import java.util.HashMap;
@@ -90,4 +91,9 @@ public class FundInformationDao {
     public List<ManualFundManagerChangeDo> listFundManagerChangeHistory(String fundId) {
         return this.fundInformationDoMapper.listFundManagerChangeHistory(fundId);
     }
+
+    public List<MfManagerFundNumDo> listMfManagerFundNumByManagerId(List<String> managerIdList) {
+        return this.fundInformationDoMapper.listMfManagerFundNumByManagerId(managerIdList);
+    }
+
 }

+ 28 - 0
src/main/java/com/smppw/analysis/domain/dataobject/ManualFundAssetSizeDo.java

@@ -0,0 +1,28 @@
+package com.smppw.analysis.domain.dataobject;
+
+import lombok.Data;
+
+/**
+ * @author mozuwen
+ * @date 2023/8/9 21:03
+ * @description 公募基金的经理在管的所有基金的某个日期的资产值
+ */
+@Data
+public class ManualFundAssetSizeDo {
+
+    /**
+     * 日期
+     */
+    private String date;
+
+    /**
+     * 基金id
+     */
+    private String fundId;
+
+    /**
+     * 基金资产值
+     */
+    private Double fundAssetSize;
+
+}

+ 63 - 0
src/main/java/com/smppw/analysis/domain/dataobject/ManualFundManagerInfoDo.java

@@ -0,0 +1,63 @@
+package com.smppw.analysis.domain.dataobject;
+
+import lombok.Data;
+
+/**
+ * @author mozuwen
+ * @date 2023/8/9 19:10
+ * @description 公募基金当前在管的基金经理信息
+ */
+@Data
+public class ManualFundManagerInfoDo {
+
+    /**
+     * id
+     */
+    private String managerId;
+
+    /**
+     * 名称
+     */
+    private String managerName;
+
+    /**
+     * 在职开始时间
+     */
+    private String startDate;
+
+    /**
+     * 在职结束时间
+     */
+    private String endDate;
+
+    /**
+     * 人员头像,93
+     */
+    private String avatar;
+
+    /**
+     * 人员头像,172
+     */
+    private String avatar2;
+
+    /**
+     * 性别
+     */
+    private String gender;
+
+    /**
+     * 性别,1-男,2-女
+     */
+    private String genderValue;
+
+    /**
+     * 公募全部产品数量
+     */
+    private String publicProductNumAll;
+
+    /**
+     * 公募正在运行产品数量
+     */
+    private String publicProductNumRunning;
+
+}

+ 37 - 0
src/main/java/com/smppw/analysis/domain/dataobject/MfManagerFundNumDo.java

@@ -0,0 +1,37 @@
+package com.smppw.analysis.domain.dataobject;
+
+import lombok.Data;
+
+/**
+ * @author mozuwen
+ * @date 2023/8/9 19:30
+ * @description 公募基金的基金经理管理的基金信息
+ */
+@Data
+public class MfManagerFundNumDo {
+
+    /**
+     * 基金id
+     */
+    private String fundId;
+
+    /**
+     * 基金经理id
+     */
+    private String managerId;
+
+    /**
+     * 基金管理开始时间
+     */
+    private String startDate;
+
+    /**
+     * 基金管理结束时间
+     */
+    private String endDate;
+
+    /**
+     * 基金运行状态:1-募集中、2-开放运行、3-封闭运行(已废弃)、4-提前清算、5-到期清算、6-发行失败、7-投顾协议已终止、 8-延期清算 -1-其他 9-非正常清算 10-已终止 11-已作废
+     */
+    private Integer status;
+}

+ 7 - 0
src/main/java/com/smppw/analysis/domain/dataobject/PersonnelInformationDo.java

@@ -21,6 +21,11 @@ public class PersonnelInformationDo {
     private String personnelName;
 
     /**
+     * 性别:1-男,2-女
+     */
+    private Integer sex;
+
+    /**
      * 人员头像1
      */
     private String avatar;
@@ -39,4 +44,6 @@ public class PersonnelInformationDo {
      * 简介
      */
     private String profile;
+
+
 }

+ 73 - 0
src/main/java/com/smppw/analysis/domain/dto/info/ManualFundManagerInfoVO.java

@@ -0,0 +1,73 @@
+package com.smppw.analysis.domain.dto.info;
+
+import lombok.Data;
+
+/**
+ * @author mozuwen
+ * @date 2023/8/9 19:10
+ * @description 公募基金详情页-基金经理
+ */
+@Data
+public class ManualFundManagerInfoVO {
+
+    /**
+     * 头像1
+     */
+    private String avatar;
+
+    /**
+     * 头像2
+     */
+    private String avatar2;
+
+    /**
+     * 性别
+     */
+    private String gender;
+
+    /**
+     * 任内年化收益率
+     */
+    private String annualRet;
+
+    /**
+     * 任内基准增长率,基准区间收益率
+     */
+    private String benchmarkRet;
+
+    /**
+     * 管理产品数量
+     */
+    private String fundNum;
+
+    /**
+     * 基金经理id
+     */
+    private String managerId;
+
+    /**
+     * 基金经理名字
+     */
+    private String managerName;
+
+    /**
+     * 任内基金净值增长率,区间收益率
+     */
+    private String navChange;
+
+    /**
+     * 存续产品数量
+     */
+    private String runningNum;
+
+    /**
+     * 存续基金资产规模
+     */
+    private String runningScale;
+
+    /**
+     * 任内夏普比率
+     */
+    private String sharpe;
+
+}

+ 24 - 0
src/main/java/com/smppw/analysis/domain/mapper/core/FundAssetSizeMapper.java

@@ -0,0 +1,24 @@
+package com.smppw.analysis.domain.mapper.core;
+
+import com.smppw.analysis.domain.dataobject.ManualFundAssetSizeDo;
+import lombok.Data;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * @author mozuwen
+ * @date 2023/8/9 21:03
+ * @description 基金资产规模Mapper
+ */
+@Repository
+public interface FundAssetSizeMapper {
+
+    /**
+     * 获取基金资产规模
+     * @param managerId 基金经理id
+     * @return 基金资产规模
+     */
+    List<ManualFundAssetSizeDo> getAssetSizeList(String managerId);
+
+}

+ 9 - 4
src/main/java/com/smppw/analysis/domain/mapper/core/FundInformationDoMapper.java

@@ -1,9 +1,6 @@
 package com.smppw.analysis.domain.mapper.core;
 
-import com.smppw.analysis.domain.dataobject.FundFeeDo;
-import com.smppw.analysis.domain.dataobject.FundInformationDo;
-import com.smppw.analysis.domain.dataobject.FundSimilarDo;
-import com.smppw.analysis.domain.dataobject.ManualFundManagerChangeDo;
+import com.smppw.analysis.domain.dataobject.*;
 import org.apache.ibatis.annotations.Param;
 import org.springframework.stereotype.Repository;
 
@@ -69,4 +66,12 @@ public interface FundInformationDoMapper {
      */
     List<ManualFundManagerChangeDo> listFundManagerChangeHistory(@Param("fundId") String fundId);
 
+    /**
+     * 获取公募基金的基金经理管理的基金信息
+     *
+     * @param managerIdList 基金经理id列表
+     * @return 公募基金的基金经理管理的基金信息
+     */
+    List<MfManagerFundNumDo> listMfManagerFundNumByManagerId(@Param("managerIdList") List<String> managerIdList);
+
 }

+ 7 - 0
src/main/java/com/smppw/analysis/domain/mapper/core/PersonnelInformationMapper.java

@@ -32,4 +32,11 @@ public interface PersonnelInformationMapper {
      */
     List<PersonnelWorkExperienceDo> listPersonnelWorkExperience(@Param("personnelIdList") List<String> personnelIdList);
 
+    /**
+     * 获取公募基金正在任职的人员基本信息
+     *
+     * @param refId 基金id
+     * @return 公募基金正在任职的人员基本信息
+     */
+    List<PersonnelInformationDo> getFundPresentManagerInfo(String refId);
 }

+ 24 - 0
src/main/java/com/smppw/analysis/domain/service/BaseInfoService.java

@@ -162,4 +162,28 @@ public interface BaseInfoService {
      * @return 公募基金的基金经理变更历史
      */
     List<ManualFundManagerChangeDo> listFundManagerChangeHistory(String fundId);
+
+    /**
+     * 获取公募基金的基金经理管理的基金信息
+     *
+     * @param managerIdList 基金经理id列表
+     * @return 公募基金的基金经理管理的基金信息
+     */
+    List<MfManagerFundNumDo> listMfManagerFundNumByManagerId(List<String> managerIdList);
+
+    /**
+     * 获取公募基金正在任职的人员基本信息
+     *
+     * @param refId 基金id
+     * @return 公募基金正在任职的人员基本信息
+     */
+    List<PersonnelInformationDo> getFundPresentManagerInfo(String refId);
+
+
+    /**
+     * 获取基金资产规模
+     * @param managerId 基金经理id
+     * @return 基金资产规模
+     */
+    List<ManualFundAssetSizeDo> getAssetSizeList(String managerId);
 }

+ 20 - 4
src/main/java/com/smppw/analysis/domain/service/impl/BaseInfoServiceImpl.java

@@ -14,6 +14,7 @@ import com.smppw.analysis.domain.event.SaveCacheEvent;
 import com.smppw.analysis.domain.gateway.CacheFactory;
 import com.smppw.analysis.domain.gateway.CacheGateway;
 import com.smppw.analysis.domain.mapper.core.CommonIndexMapper;
+import com.smppw.analysis.domain.mapper.core.FundAssetSizeMapper;
 import com.smppw.analysis.domain.mapper.core.MfChargeRateMapper;
 import com.smppw.analysis.domain.mapper.core.PersonnelInformationMapper;
 import com.smppw.analysis.domain.service.BaseInfoService;
@@ -71,11 +72,13 @@ public class BaseInfoServiceImpl implements BaseInfoService, ApplicationContextA
     private ApplicationContext applicationContext;
     @Autowired
     private CommonIndexMapper commonIndexMapper;
+    private final FundAssetSizeMapper fundAssetSizeMapper;
 
     public BaseInfoServiceImpl(AnalysisProperty property, CacheFactory factory, RankFactory rankFactory,
                                IndexesProfileDao indexesProfileDao, RongzhiIndexNavDao rongzhiIndexNavDao,
                                FundInformationDao fundInformationDao, FundAnnounceDao fundAnnounceDao,
-                               FundArchivesDao fundArchivesDao, MfChargeRateMapper mfChargeRateMapper, PersonnelInformationMapper personnelInformationMapper) {
+                               FundArchivesDao fundArchivesDao, MfChargeRateMapper mfChargeRateMapper,
+                               PersonnelInformationMapper personnelInformationMapper, FundAssetSizeMapper fundAssetSizeMapper) {
         this.rankDao = rankFactory.getInstance(property.getDataSource());
         this.cacheGateway = factory.getCacheGateway(property.getCacheType());
         this.indexesProfileDao = indexesProfileDao;
@@ -85,6 +88,7 @@ public class BaseInfoServiceImpl implements BaseInfoService, ApplicationContextA
         this.fundArchivesDao = fundArchivesDao;
         this.mfChargeRateMapper = mfChargeRateMapper;
         this.personnelInformationMapper = personnelInformationMapper;
+        this.fundAssetSizeMapper = fundAssetSizeMapper;
     }
 
     @Override
@@ -230,9 +234,6 @@ public class BaseInfoServiceImpl implements BaseInfoService, ApplicationContextA
             // 市场指数
             List<String> marketIndexIds = ListUtil.of(SecType.INDEX_FUND, SecType.RONGZHI_INDEX, SecType.THIRD_INDEX_FUND);
             this.loadNameMap(secNameMap, typeSecMap, marketIndexIds, this.indexesProfileDao::getFundIdNameMap);
-            // 策略
-            List<String> strategyIds = ListUtil.of(SecType.STRATEGY);
-            this.loadNameMap(secNameMap, typeSecMap, strategyIds, this::getStrategyIdNameMap);
             // 推送事件,存缓存
             SaveCacheEvent<Map<String, Object>> event = new SaveCacheEvent<>(key, secNameMap, t -> {
                 this.cacheGateway.hset(key, t);
@@ -318,6 +319,21 @@ public class BaseInfoServiceImpl implements BaseInfoService, ApplicationContextA
         return fundInformationDao.listFundManagerChangeHistory(fundId);
     }
 
+    @Override
+    public List<MfManagerFundNumDo> listMfManagerFundNumByManagerId(List<String> managerIdList) {
+        return fundInformationDao.listMfManagerFundNumByManagerId(managerIdList);
+    }
+
+    @Override
+    public List<PersonnelInformationDo> getFundPresentManagerInfo(String refId) {
+        return personnelInformationMapper.getFundPresentManagerInfo(refId);
+    }
+
+    @Override
+    public List<ManualFundAssetSizeDo> getAssetSizeList(String managerId) {
+        return fundAssetSizeMapper.getAssetSizeList(managerId);
+    }
+
     /**
      * 把指定类型的标的的名称映射查询出来
      *

+ 19 - 0
src/main/resources/mapping/core/FundAssetSizeMapper.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.smppw.analysis.domain.mapper.core.FundAssetSizeMapper">
+
+    <select id="getAssetSizeList" resultType="com.smppw.analysis.domain.dataobject.ManualFundAssetSizeDo">
+        select t.fund_id as fundId, t.fund_asset_size as fundAssetSize, t.fund_asset_size_date as `date`
+        from rz_hfdb_core.fund_asset_size t
+        where t.fund_id in (select distinct a.fund_id
+                            from rz_hfdb_core.fund_information a
+                                     join rz_hfdb_core.fund_manager_mapping b
+                                          on a.fund_id = b.fund_id and b.management_end_date is null and b.isvalid = 1
+                                     left join rz_hfdb_core.fund_status fs
+                                               on a.fund_id = fs.fund_id and fs.liquidate_date is null
+                            where b.fund_manager_id = #{managerId}
+                              and a.isvalid = 1
+                              and a.raise_type = 2)
+    </select>
+
+</mapper>

+ 18 - 0
src/main/resources/mapping/core/FundInformationDoMapper.xml

@@ -355,4 +355,22 @@
         order by startDate desc
     </select>
 
+    <select id="listMfManagerFundNumByManagerId"
+            resultType="com.smppw.analysis.domain.dataobject.MfManagerFundNumDo">
+        select t1.personnel_id          as managerId,
+               t2.fund_id               as fundId,
+               t2.management_start_date as startDate,
+               t2.management_end_date   as endDate,
+               t3.fund_status as status
+        from rz_hfdb_core.personnel_information t1
+                 join rz_hfdb_core.fund_manager_mapping t2
+                      on t1.personnel_id = t2.fund_manager_id and t2.isvalid = 1
+        join  rz_hfdb_core.fund_status t3 on t2.fund_id = t3.fund_id and t3.isvalid=1
+        where t1.isvalid = 1
+          and t1.personnel_id in
+            <foreach collection="managerIdList" item="managerId" index="index" open="(" separator="," close=")">
+                #{managerId}
+            </foreach>
+    </select>
+
 </mapper>

+ 17 - 0
src/main/resources/mapping/core/PersonnelInformationMapper.xml

@@ -8,6 +8,7 @@
                t1.personnel_name as personnelName,
                t1.avatar         as avatar,
                t1.avatar2        as avatar2,
+               t1.sex            as sex,
                t1.education      as education,
                t1.profile        as profile
         from rz_hfdb_core.personnel_information t1
@@ -43,4 +44,20 @@
         ORDER BY t1.start_date DESC, t1.company_id DESC
     </select>
 
+    <select id="getFundPresentManagerInfo"
+            resultType="com.smppw.analysis.domain.dataobject.PersonnelInformationDo">
+        select t1.personnel_id   as personnelId,
+               t1.personnel_name as personnelName,
+               t1.avatar         as avatar,
+               t1.avatar2        as avatar2,
+               t1.sex            as sex,
+               t1.education      as education,
+               t1.profile        as profile
+        from rz_hfdb_core.personnel_information t1
+                 inner join rz_hfdb_core.fund_manager_mapping t2
+                            on t1.personnel_id = t2.fund_manager_id and t2.isvalid = 1
+        where t2.fund_id = #{refId} and t2.management_end_date is null
+          and t1.isvalid = 1
+    </select>
+
 </mapper>