<commit_before>package org.innovateuk.ifs.project.spendprofile.transactional;

import org.innovateuk.ifs.finance.resource.ProjectFinanceResource;
import org.innovateuk.ifs.finance.resource.cost.SbriPilotCostCategoryGenerator;
import org.innovateuk.ifs.finance.transactional.ProjectFinanceService;
import org.innovateuk.ifs.organisation.domain.Organisation;
import org.innovateuk.ifs.procurement.milestone.resource.ProjectProcurementMilestoneResource;
import org.innovateuk.ifs.procurement.milestone.transactional.ProjectProcurementMilestoneService;
import org.innovateuk.ifs.project.core.domain.Project;
import org.innovateuk.ifs.project.financechecks.domain.Cost;
import org.innovateuk.ifs.project.financechecks.domain.CostCategory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;

import static java.math.BigDecimal.ONE;
import static java.math.BigInteger.ZERO;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static java.util.stream.IntStream.range;
import static org.innovateuk.ifs.finance.resource.cost.SbriPilotCostCategoryGenerator.OTHER_COSTS;
import static org.innovateuk.ifs.finance.resource.cost.SbriPilotCostCategoryGenerator.VAT;
import static org.innovateuk.ifs.project.finance.resource.TimeUnit.MONTH;

@Component
public class ProcurementMilestonesSpendProfileFigureDistributer {

    @Autowired
    private ProjectProcurementMilestoneService projectProcurementMilestoneService;

    @Autowired
    private ProjectFinanceService projectFinanceService;

    public List<List<Cost>> distributeCosts(SpendProfileCostCategorySummaries costCategorySummaries, Project project, Organisation organisation) {


        ProjectFinanceResource projectFinance = projectFinanceService.financeChecksDetails(project.getId(), organisation.getId()).getSuccess();
        List<ProjectProcurementMilestoneResource> milestones = projectProcurementMilestoneService.getByProjectId(project.getId()).getSuccess();
        Long durationInMonths = project.getDurationInMonths();
        BigDecimal vatRate = projectFinance.getVatRate();
        CostCategory otherCostCategory = costCategory(costCategorySummaries, OTHER_COSTS);
        CostCategory vatCostCategory = costCategory(costCategorySummaries, VAT);
        List<BigInteger> milestoneTotalsPerMonth = milestoneTotalsPerMonth(durationInMonths.intValue(), milestones);
        List<OtherAndVat> costs = distributeWithVat(milestoneTotalsPerMonth, otherCostCategory, vatCostCategory, vatRate);
        List<OtherAndVat> adjustedCosts = adjustedCosts(costs, costCategorySummaries);
        return toCosts(adjustedCosts, otherCostCategory, vatCostCategory);
    }

    private List<List<Cost>> toCosts(List<OtherAndVat> costs, CostCategory otherCostCategory, CostCategory vatCostCategory){
        List<Cost> vat = range(0, costs.size())
                .mapToObj(index -> new Cost(new BigDecimal(costs.get(index).vat))
                        .withCategory(vatCostCategory)
                        .withTimePeriod(index, MONTH, 1, MONTH))
                .collect(toList());
        List<Cost> otherCosts = range(0, costs.size())
                .mapToObj(index -> new Cost(new BigDecimal(costs.get(index).vat))
                        .withCategory(otherCostCategory)
                        .withTimePeriod(index, MONTH, 1, MONTH))
                .collect(toList());
        return asList(otherCosts, vat);
    }

    private List<OtherAndVat> adjustedCosts(List<OtherAndVat> costsToAdjust, SpendProfileCostCategorySummaries  costCategorySummaries){
        BigInteger toSumToVat = cost(costCategorySummaries, VAT).getTotal().toBigInteger();
        BigInteger toSumToOtherCosts = cost(costCategorySummaries, OTHER_COSTS).getTotal().toBigInteger();
        BigInteger currentVatTotal = costsToAdjust.stream().map(otherAndVat -> otherAndVat.vat).reduce(BigInteger::add).orElse(ZERO);
        BigInteger currentOtherCostsTotal = costsToAdjust.stream().map(otherAndVat -> otherAndVat.other).reduce(BigInteger::add).orElse(ZERO);
        return range(0, costsToAdjust.size()).mapToObj(index ->
        {
            OtherAndVat current = costsToAdjust.get(index);
            if (index == costsToAdjust.size() - 1){
                return current;
            }
            return new OtherAndVat(current.other.add(toSumToOtherCosts.subtract(currentOtherCostsTotal)),<commit_msg>IFS-8945 fixing error<commit_after>package org.innovateuk.ifs.project.spendprofile.transactional;

import org.innovateuk.ifs.finance.resource.ProjectFinanceResource;
import org.innovateuk.ifs.finance.resource.cost.SbriPilotCostCategoryGenerator;
import org.innovateuk.ifs.finance.transactional.ProjectFinanceService;
import org.innovateuk.ifs.organisation.domain.Organisation;
import org.innovateuk.ifs.procurement.milestone.resource.ProjectProcurementMilestoneResource;
import org.innovateuk.ifs.procurement.milestone.transactional.ProjectProcurementMilestoneService;
import org.innovateuk.ifs.project.core.domain.Project;
import org.innovateuk.ifs.project.financechecks.domain.Cost;
import org.innovateuk.ifs.project.financechecks.domain.CostCategory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;

import static java.math.BigDecimal.ONE;
import static java.math.BigInteger.ZERO;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static java.util.stream.IntStream.range;
import static org.innovateuk.ifs.finance.resource.cost.SbriPilotCostCategoryGenerator.OTHER_COSTS;
import static org.innovateuk.ifs.finance.resource.cost.SbriPilotCostCategoryGenerator.VAT;
import static org.innovateuk.ifs.project.finance.resource.TimeUnit.MONTH;

@Component
public class ProcurementMilestonesSpendProfileFigureDistributer {

    @Autowired
    private ProjectProcurementMilestoneService projectProcurementMilestoneService;

    @Autowired
    private ProjectFinanceService projectFinanceService;

    public List<List<Cost>> distributeCosts(SpendProfileCostCategorySummaries costCategorySummaries, Project project, Organisation organisation) {


        ProjectFinanceResource projectFinance = projectFinanceService.financeChecksDetails(project.getId(), organisation.getId()).getSuccess();
        List<ProjectProcurementMilestoneResource> milestones = projectProcurementMilestoneService.getByProjectId(project.getId()).getSuccess();
        Long durationInMonths = project.getDurationInMonths();
        BigDecimal vatRate = projectFinance.getVatRate();
        CostCategory otherCostCategory = costCategory(costCategorySummaries, OTHER_COSTS);
        CostCategory vatCostCategory = costCategory(costCategorySummaries, VAT);
        List<BigInteger> milestoneTotalsPerMonth = milestoneTotalsPerMonth(durationInMonths.intValue(), milestones);
        List<OtherAndVat> costs = distributeWithVat(milestoneTotalsPerMonth, otherCostCategory, vatCostCategory, vatRate);
        List<OtherAndVat> adjustedCosts = adjustedCosts(costs, costCategorySummaries);
        return toCosts(adjustedCosts, otherCostCategory, vatCostCategory);
    }

    private List<List<Cost>> toCosts(List<OtherAndVat> costs, CostCategory otherCostCategory, CostCategory vatCostCategory){
        List<Cost> vat = range(0, costs.size())
                .mapToObj(index -> new Cost(new BigDecimal(costs.get(index).vat))
                        .withCategory(vatCostCategory)
                        .withTimePeriod(index, MONTH, 1, MONTH))
                .collect(toList());
        List<Cost> otherCosts = range(0, costs.size())
                .mapToObj(index -> new Cost(new BigDecimal(costs.get(index).other))
                        .withCategory(otherCostCategory)
                        .withTimePeriod(index, MONTH, 1, MONTH))
                .collect(toList());
        return asList(otherCosts, vat);
    }

    private List<OtherAndVat> adjustedCosts(List<OtherAndVat> costsToAdjust, SpendProfileCostCategorySummaries  costCategorySummaries){
        BigInteger toSumToVat = cost(costCategorySummaries, VAT).getTotal().toBigInteger();
        BigInteger toSumToOtherCosts = cost(costCategorySummaries, OTHER_COSTS).getTotal().toBigInteger();
        BigInteger currentVatTotal = costsToAdjust.stream().map(otherAndVat -> otherAndVat.vat).reduce(BigInteger::add).orElse(ZERO);
        BigInteger currentOtherCostsTotal = costsToAdjust.stream().map(otherAndVat -> otherAndVat.other).reduce(BigInteger::add).orElse(ZERO);
        return range(0, costsToAdjust.size()).mapToObj(index ->
        {
            OtherAndVat current = costsToAdjust.get(index);
            if (index != costsToAdjust.size() - 1){
                return current;
            }
            return new OtherAndVat(current.other.add(toSumToOtherCosts.subtract(currentOtherCostsTotal)),
{'fraction_non_alphanumeric': 0.09379810864306136, 'fraction_numerical': 0.0017594018033868484, 'mean_word_length': 4.642059553349876, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6654128', 'n_tokens_mistral': 2662, 'n_tokens_neox': 2586, 'n_words': 383}