package com.mstar.meds2.segment.qc.rule;
import com.morningstar.ge.util.collection.ListUtils;
import com.mstar.meds.base.dal.DALException;
import com.mstar.meds.base.util.DateFormatUtils;
import com.mstar.meds2.V2QcLog;
import com.mstar.meds2.enums.SegmentDataPointEnum;
import com.mstar.meds2.enums.SegmentQcLocationTypeEnum;
import com.mstar.meds2.model.SimpleCompanyInfo;
import com.mstar.meds2.qc.servicebase.QcRuleBase;
import com.mstar.meds2.qc.utils.V2QcLogHelper;
import com.mstar.meds2.segment.SegmentDataPoint;
import com.mstar.meds2.segment.SegmentReport;
import com.mstar.meds2.segment.SegmentValue;
import com.mstar.meds2.segment.loading.SegmentDpLoader;
import org.apache.commons.lang.StringUtils;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* Created by jliang5 on 12/27 0027.
*/
public class SegmentValueCompanyTotalVsAsReportedTotal extends QcRuleBase {
List<SegmentValue> segmentTotalAllValues ;
@Override
protected void doCheck() throws Exception {
for (Integer fileId : qcData.getChangedFileIds()) {
List<SegmentReport> segmentReports = qcData.getOneDocSegmentReportsByFileId(fileId);
List<String> datapointQcList = new ArrayList<>();
SimpleCompanyInfo companyInfo = qcData.getCompanyInfo();
if(ListUtils.isNotEmpty(segmentReports)){
for (SegmentReport eachReport : segmentReports) {
if(docHasRuledp(companyInfo,fileId,eachReport,datapointQcList)){
BigDecimal companyTotal = getCompanyTotal(eachReport);
BigDecimal segmentTotal = calculateValue(segmentTotalAllValues);
if(companyTotal.compareTo(BigDecimal.ZERO) != 0 && segmentTotal.compareTo(BigDecimal.ZERO) != 0){
if(companyTotal.subtract(segmentTotal).divide(companyTotal,2,BigDecimal.ROUND_HALF_UP).abs().compareTo(new BigDecimal(0.1)) == 1){
this.logInfo(fileId,eachReport,companyTotal,segmentTotal,datapointQcList);
}
}else {
if(companyTotal.subtract(segmentTotal).abs().compareTo(new BigDecimal(0.1)) == 1){
this.logInfo(fileId,eachReport,companyTotal,segmentTotal,datapointQcList);
}
}
}
}
}
}
}
private BigDecimal getCompanyTotal(SegmentReport eachReport) {
BigDecimal companyTotal = null;
if(this.getLogicExpression().equalsIgnoreCase(SegmentDataPointEnum.Total_Revenue.getName())){
companyTotal = eachReport.getTotalRevenue();
}else if(this.getLogicExpression().equalsIgnoreCase(SegmentDataPointEnum.Operating_Income.getName())){
companyTotal = eachReport.getTotalOperatingIncome();
}else if(this.getLogicExpression().equalsIgnoreCase(SegmentDataPointEnum.Net_Income.getName())){
companyTotal = eachReport.getTotalNetIncome();
}else {
companyTotal = eachReport.getTotalAssets();
}
if(null == companyTotal){
companyTotal = BigDecimal.ZERO;
}
return companyTotal;
}
private boolean docHasRuledp(SimpleCompanyInfo companyInfo, Integer fileId, SegmentReport report, List<String> datapointQcList) throws DALException {
boolean hasRuleDp = false;
if(this.getLogicExpression().trim().equals("Total Asset")){
this.setLogicExpression("Total Assets");
}
List<SegmentValue> fatherDatapointAllValues = qcData.getOneDatapointAllValues(report.getReportId(), SegmentDataPointEnum.getValueByName(this.getLogicExpression().trim()));
if(ListUtils.isNotEmpty(fatherDatapointAllValues)) {
hasRuleDp = true;
datapointQcList.add(SegmentDataPointEnum.getValueByName(this.getLogicExpression().trim()));
segmentTotalAllValues = fatherDatapointAllValues;
}else{
List<SegmentValue> childrenDatapointAllValues = getRollUpValueList(companyInfo, fileId, report,datapointQcList);
if(ListUtils.isNotEmpty(childrenDatapointAllValues)){
hasRuleDp = true;
segmentTotalAllValues = childrenDatapointAllValues;
}
}
return hasRuleDp;
}
private List<SegmentValue> getRollUpValueList(SimpleCompanyInfo companyInfo, Integer fileId, SegmentReport report,List<String> datapointQcList) throws DALException {
List<SegmentValue> rollUpValueList = new ArrayList<>();
List<SegmentDataPoint> rollUpDpChildren = getRollUpDpChildren(companyInfo);
if(ListUtils.isNotEmpty(rollUpDpChildren) && !rollUpDpChildren.get(0).getDataPointId().equals(SegmentDataPointEnum.Non_Current_Assets.getValue())){
for (SegmentDataPoint eachChildDp : rollUpDpChildren) {
datapointQcList.add(eachChildDp.getDataPointId());
rollUpValueList.addAll(qcData.getOneDatapointAllValues(report.getReportId(), eachChildDp.getDataPointId()));
}
}
return rollUpValueList;
}
private List<SegmentDataPoint> getRollUpDpChildren(SimpleCompanyInfo companyInfo) {
List<SegmentDataPoint> rollUpChildren = new ArrayList<>();
List<SegmentDataPoint> dataPointList = SegmentDpLoader.getInstance().getSegmentDpByFileSourceAndIndustryCode(companyInfo.getFileSource(), companyInfo.getIndustryTemplateCode());
for (SegmentDataPoint eachDp : dataPointList) {
if(eachDp.getRollUpTo() != null
&& eachDp.getRollUpTo().equalsIgnoreCase(SegmentDataPointEnum.getValueByName(this.getLogicExpression().trim()))
&& !eachDp.getDataPointId().equalsIgnoreCase(eachDp.getRollUpTo())){
rollUpChildren.add(eachDp);
}
}
return rollUpChildren;
}
private BigDecimal calculateValue(List<SegmentValue> segmentTotalValueList) {
BigDecimal result = BigDecimal.ZERO;
if(ListUtils.isNotEmpty(segmentTotalValueList)){
for (SegmentValue eachValue : segmentTotalValueList) {
BigDecimal value = eachValue.getValue();
if(value != null){
result = result.add(value);
}
}
}
return result;
}
private void logInfo(Integer fileId, SegmentReport report, BigDecimal value1, BigDecimal value2,List<String> datapointQcList){
String showInfo = this.getShowInfo(fileId,report,value1,value2);
StringBuilder sb = new StringBuilder();
sb.append("header_"+SegmentQcLocationTypeEnum.DATALOCATION.getDescription() + "_" + report.getReportId() + "_" + replaceBlankSpace(this.getLogicExpression().trim().toLowerCase()));
for (String eachDpId : datapointQcList) {
sb.append("||").append("values_"+SegmentQcLocationTypeEnum.AREALOCATION.getDescription() + "_" + report.getReportId() + "_" + eachDpId);
}
V2QcLog log = V2QcLogHelper.generateSegmentQcLog(ruleId, qcData.getCompanyId(), qcData.getTableType(), fileId, showInfo, sb.toString());
this.addLog(log);
}
private String getShowInfo(Integer fileId,SegmentReport report,BigDecimal value1,BigDecimal value2){
StringBuilder sb = new StringBuilder();
sb.append("DocId: " +fileId+ ",PED: " + DateFormatUtils.format(report.getPeriodEndDate(),"yyyy-MM-dd") + ",CompanyLevelTotal: " + value1);
sb.append(" || ");
sb.append("DocId: " +fileId+ ",PED: " + DateFormatUtils.format(report.getPeriodEndDate(),"yyyy-MM-dd") + ",SegmentTotal: " + value2);
return sb.toString();
}
private String replaceBlankSpace(String str) {
if (StringUtils.isBlank(str)) {
return str;
}
return str.replaceAll("\\s|\t| |_", "");
}
}