|
@@ -1,57 +1,144 @@
|
|
package com.smppw.modaq.application.components.report.parser.ai;
|
|
package com.smppw.modaq.application.components.report.parser.ai;
|
|
|
|
|
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
|
+import cn.hutool.core.collection.ListUtil;
|
|
|
|
+import cn.hutool.core.map.MapUtil;
|
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
|
+import com.smppw.modaq.application.components.ReportParseUtils;
|
|
import com.smppw.modaq.application.components.report.parser.ReportParserConstant;
|
|
import com.smppw.modaq.application.components.report.parser.ReportParserConstant;
|
|
import com.smppw.modaq.common.enums.ReportParseStatus;
|
|
import com.smppw.modaq.common.enums.ReportParseStatus;
|
|
import com.smppw.modaq.common.exception.ReportParseException;
|
|
import com.smppw.modaq.common.exception.ReportParseException;
|
|
-import com.smppw.modaq.domain.dto.report.QuarterlyReportData;
|
|
|
|
-import com.smppw.modaq.domain.dto.report.ReportBaseInfoDTO;
|
|
|
|
-import com.smppw.modaq.domain.dto.report.ReportFundInfoDTO;
|
|
|
|
-import com.smppw.modaq.domain.dto.report.ReportParserParams;
|
|
|
|
|
|
+import com.smppw.modaq.domain.dto.report.*;
|
|
import com.smppw.modaq.domain.mapper.EmailFieldMappingMapper;
|
|
import com.smppw.modaq.domain.mapper.EmailFieldMappingMapper;
|
|
import org.springframework.stereotype.Component;
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
|
|
+import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
|
|
@Component(ReportParserConstant.PARSER_AI_QUARTERLY)
|
|
@Component(ReportParserConstant.PARSER_AI_QUARTERLY)
|
|
-public class AIQuarterlyReportParser extends AbstractAIReportParser<QuarterlyReportData> {
|
|
|
|
|
|
+public class AIQuarterlyReportParser<T extends QuarterlyReportData> extends AbstractAIReportParser<T> {
|
|
public AIQuarterlyReportParser(EmailFieldMappingMapper fieldMappingMapper) {
|
|
public AIQuarterlyReportParser(EmailFieldMappingMapper fieldMappingMapper) {
|
|
super(fieldMappingMapper);
|
|
super(fieldMappingMapper);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
protected boolean isSupportAIParse() {
|
|
protected boolean isSupportAIParse() {
|
|
- return false;
|
|
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
protected String prompt() {
|
|
protected String prompt() {
|
|
return """
|
|
return """
|
|
- 识别文件中的基金基本情况、主要财务指标、投资组合情况、基金份额变动情况,
|
|
|
|
- 主要财务指标可能包含分级基金数据,投资组合情况包含期末基金资产组合情况、报告期末按行业分类的股票投资组合,
|
|
|
|
- 要求解析结果的中文符号转英文符号,结果用json返回
|
|
|
|
|
|
+ 识别文件中的基金基本情况、投资组合情况,
|
|
|
|
+ 投资组合情况包含期末基金资产组合情况、报告期末按行业分类的股票投资组合,
|
|
|
|
+ 报告期末按行业分类的股票投资组合又包含报告期末按行业分类的境内股票投资组合、报告期末按行业分类的港股通投资股票投资组合,
|
|
|
|
+ 要求准确识别金额等小数的位数,结果用json返回
|
|
""";
|
|
""";
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- protected QuarterlyReportData parseExtInfoAndSetData(ReportBaseInfoDTO reportInfo,
|
|
|
|
- ReportFundInfoDTO fundInfo) throws ReportParseException {
|
|
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
+ protected T parseExtInfoAndSetData(ReportBaseInfoDTO reportInfo,
|
|
|
|
+ ReportFundInfoDTO fundInfo) throws ReportParseException {
|
|
QuarterlyReportData reportData = new QuarterlyReportData(reportInfo, fundInfo);
|
|
QuarterlyReportData reportData = new QuarterlyReportData(reportInfo, fundInfo);
|
|
- reportData.setAssetAllocation(null);
|
|
|
|
|
|
+ // 这俩有分级基金,先不解析
|
|
reportData.setShareChange(null);
|
|
reportData.setShareChange(null);
|
|
reportData.setFinancialIndicators(null);
|
|
reportData.setFinancialIndicators(null);
|
|
- reportData.setInvestmentIndustry(null);
|
|
|
|
- return reportData;
|
|
|
|
|
|
+ // 资产配置组合
|
|
|
|
+ Integer fileId = reportInfo.getFileId();
|
|
|
|
+ String reportName = reportInfo.getReportName();
|
|
|
|
+ Object assetInfo = this.allInfoMap.get("投资组合情况");
|
|
|
|
+ if (assetInfo == null) {
|
|
|
|
+ throw new ReportParseException(ReportParseStatus.PARSE_ASSET_INFO_FAIL, reportName);
|
|
|
|
+ }
|
|
|
|
+ Map<String, Object> assetInfoMap = (Map<String, Object>) assetInfo;
|
|
|
|
+ reportData.setAssetAllocation(this.buildAssetAllocationInfo(fileId, reportName, assetInfoMap));
|
|
|
|
+ reportData.setInvestmentIndustry(this.buildInvestmentIndustryInfo(fileId, reportName, assetInfoMap));
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
+ T t = (T) reportData;
|
|
|
|
+ return t;
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
protected ReportFundInfoDTO buildFundInfo(ReportParserParams params) {
|
|
protected ReportFundInfoDTO buildFundInfo(ReportParserParams params) {
|
|
// 获取并移除基金基本情况信息
|
|
// 获取并移除基金基本情况信息
|
|
- Object fundInfo = this.allInfoMap.remove("基金基本情况");
|
|
|
|
|
|
+ Object fundInfo = this.allInfoMap.get("基金基本情况");
|
|
if (fundInfo == null) {
|
|
if (fundInfo == null) {
|
|
throw new ReportParseException(ReportParseStatus.PARSE_FUND_INFO_FAIL, params.getFilename());
|
|
throw new ReportParseException(ReportParseStatus.PARSE_FUND_INFO_FAIL, params.getFilename());
|
|
}
|
|
}
|
|
Map<String, Object> fundInfoMap = (Map<String, Object>) fundInfo;
|
|
Map<String, Object> fundInfoMap = (Map<String, Object>) fundInfo;
|
|
return this.buildDto(params.getFileId(), ReportFundInfoDTO.class, fundInfoMap);
|
|
return this.buildDto(params.getFileId(), ReportFundInfoDTO.class, fundInfoMap);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
+ private List<ReportAssetAllocationDTO> buildAssetAllocationInfo(Integer fileId, String reportName,
|
|
|
|
+ Map<String, Object> assetInfoMap) {
|
|
|
|
+ Object allocationInfo = assetInfoMap.get("期末基金资产组合情况");
|
|
|
|
+ if (allocationInfo == null) {
|
|
|
|
+ throw new ReportParseException(ReportParseStatus.PARSE_ASSET_INFO_FAIL, reportName);
|
|
|
|
+ }
|
|
|
|
+ List<Map<String, Object>> allocationList = ListUtil.list(false);
|
|
|
|
+ try {
|
|
|
|
+ allocationList = (List<Map<String, Object>>) allocationInfo;
|
|
|
|
+ } catch (Exception ignored) {
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ List<ReportAssetAllocationDTO> dtos = ListUtil.list(false);
|
|
|
|
+ for (Map<String, Object> allocation : allocationList) {
|
|
|
|
+ String detail = ReportParseUtils.cleaningValue(allocation.get("项目"));
|
|
|
|
+ if (!ReportParseUtils.ASSET_ALLOCATION_TYPE_MAPPER.containsKey(detail)) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ String marketValueAndRemark = ReportParseUtils.cleaningValue(allocation.get("金额"), false);
|
|
|
|
+ // 大类
|
|
|
|
+ ReportParseUtils.buildAssetAllocation(fileId, detail, marketValueAndRemark, dtos);
|
|
|
|
+ }
|
|
|
|
+ return dtos;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
+ private List<ReportInvestmentIndustryDTO> buildInvestmentIndustryInfo(Integer fileId, String reportName,
|
|
|
|
+ Map<String, Object> assetInfoMap) {
|
|
|
|
+ Object industryInfo = assetInfoMap.get("报告期末按行业分类的股票投资组合");
|
|
|
|
+ if (industryInfo == null) {
|
|
|
|
+ throw new ReportParseException(ReportParseStatus.PARSE_INDUSTRY_INFO_FAIL, reportName);
|
|
|
|
+ }
|
|
|
|
+ Map<String, Object> industryMap = MapUtil.empty();
|
|
|
|
+ try {
|
|
|
|
+ industryMap = (Map<String, Object>) industryInfo;
|
|
|
|
+ } catch (Exception ignored) {
|
|
|
|
+ }
|
|
|
|
+ List<ReportInvestmentIndustryDTO> dtos = ListUtil.list(false);
|
|
|
|
+ this.buildIndustryInfo(fileId, 1, industryMap, dtos);
|
|
|
|
+ this.buildIndustryInfo(fileId, 2, industryMap, dtos);
|
|
|
|
+ return dtos;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
+ private void buildIndustryInfo(Integer fileId, Integer industryType,
|
|
|
|
+ Map<String, Object> industryMap,
|
|
|
|
+ List<ReportInvestmentIndustryDTO> dtos) {
|
|
|
|
+ String industryKey = industryType == 1 ? "报告期末按行业分类的境内股票投资组合" : "报告期末按行业分类的港股通投资股票投资组合";
|
|
|
|
+ List<Map<String, Object>> industryList = ListUtil.list(false);
|
|
|
|
+ try {
|
|
|
|
+ industryList = (List<Map<String, Object>>) industryMap.get(industryKey);
|
|
|
|
+ } catch (Exception ignored) {
|
|
|
|
+ }
|
|
|
|
+ if (CollUtil.isEmpty(industryList)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ for (Map<String, Object> industry : industryList) {
|
|
|
|
+ String industryName = ReportParseUtils.cleaningValue(industry.get("行业类别"));
|
|
|
|
+ if (StrUtil.isBlank(industryName) || !ReportParseUtils.INDUSTRY_COLUMN_NAMES.contains(industryName)) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ ReportInvestmentIndustryDTO dto = new ReportInvestmentIndustryDTO(fileId);
|
|
|
|
+ dto.setInvestType(industryType);
|
|
|
|
+ dto.setIndustryName(industryName);
|
|
|
|
+ dto.setMarketValue(ReportParseUtils.cleaningValue(industry.get("公允价值")));
|
|
|
|
+ dto.setRatio(ReportParseUtils.cleaningValue(industry.get("占基金资产净值比例(%)")));
|
|
|
|
+ dtos.add(dto);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|