@ApiOperation(
      value =
          "Cost effectiveness of Awards: Displays the total amount of active awards grouped by year."
              + "The tender entity, for each award, has to have amount value. The year is calculated from "
              + "tender.tenderPeriod.startDate")
  @RequestMapping(
      value = "/api/costEffectivenessAwardAmount",
      method = {RequestMethod.POST, RequestMethod.GET},
      produces = "application/json")
  public List<DBObject> costEffectivenessAwardAmount(
      @ModelAttribute @Valid final YearFilterPagingRequest filter) {

    DBObject project = new BasicDBObject();
    project.put("year", new BasicDBObject("$year", "$tender.tenderPeriod.startDate"));
    project.put("awards.value.amount", 1);
    project.put(
        "totalAwardsWithTender",
        new BasicDBObject(
            "$cond",
            Arrays.asList(
                new BasicDBObject("$gt", Arrays.asList("$tender.tenderPeriod.startDate", null)),
                1,
                0)));
    project.put(
        "awardsWithTenderValue",
        new BasicDBObject(
            "$cond",
            Arrays.asList(
                new BasicDBObject("$gt", Arrays.asList("$tender.tenderPeriod.startDate", null)),
                "$awards.value.amount",
                0)));

    DBObject project1 = new BasicDBObject();
    project1.put(Fields.UNDERSCORE_ID, 1);
    project1.put(Keys.TOTAL_AWARD_AMOUNT, 1);
    project1.put(Keys.TOTAL_AWARDS, 1);
    project1.put(Keys.TOTAL_AWARDS_WITH_TENDER, 1);
    project1.put(
        Keys.PERCENTAGE_AWARDS_WITH_TENDER,
        new BasicDBObject(
            "$multiply",
            Arrays.asList(
                new BasicDBObject(
                    "$divide", Arrays.asList("$totalAwardsWithTender", "$totalAwards")),
                100)));

    Aggregation agg =
        Aggregation.newAggregation(
            match(
                where("awards")
                    .elemMatch(where("status").is(Award.Status.active.toString()))
                    .and("awards.date")
                    .exists(true)
                    .and("tender.tenderPeriod.startDate")
                    .exists(true)),
            getMatchDefaultFilterOperation(filter),
            unwind("$awards"),
            match(
                where("awards.status")
                    .is(Award.Status.active.toString())
                    .and("awards.value")
                    .exists(true)
                    .andOperator(
                        getYearDefaultFilterCriteria(filter, "tender.tenderPeriod.startDate"))),
            new CustomProjectionOperation(project),
            group("$year")
                .sum("awardsWithTenderValue")
                .as(Keys.TOTAL_AWARD_AMOUNT)
                .count()
                .as(Keys.TOTAL_AWARDS)
                .sum("totalAwardsWithTender")
                .as(Keys.TOTAL_AWARDS_WITH_TENDER),
            new CustomProjectionOperation(project1),
            sort(Direction.ASC, Fields.UNDERSCORE_ID),
            skip(filter.getSkip()),
            limit(filter.getPageSize()));

    AggregationResults<DBObject> results = mongoTemplate.aggregate(agg, "release", DBObject.class);
    List<DBObject> tagCount = results.getMappedResults();
    return tagCount;
  }
  @ApiOperation(
      value =
          "Cost effectiveness of Tenders:"
              + " Displays the total amount of the active tenders that have active awards, "
              + "grouped by year. Only tenders.status=active"
              + "are taken into account. The year is calculated from tenderPeriod.startDate")
  @RequestMapping(
      value = "/api/costEffectivenessTenderAmount",
      method = {RequestMethod.POST, RequestMethod.GET},
      produces = "application/json")
  public List<DBObject> costEffectivenessTenderAmount(
      @ModelAttribute @Valid final GroupingFilterPagingRequest filter) {

    DBObject project = new BasicDBObject();
    project.put("year", new BasicDBObject("$year", "$tender.tenderPeriod.startDate"));
    project.put("tender.value.amount", 1);
    project.put(Fields.UNDERSCORE_ID, "$tender._id");
    project.put(
        "tenderWithAwards",
        new BasicDBObject(
            "$cond",
            Arrays.asList(
                new BasicDBObject(
                    "$eq", Arrays.asList("$awards.status", Award.Status.active.toString())),
                1,
                0)));
    project.put(
        "tenderWithAwardsValue",
        new BasicDBObject(
            "$cond",
            Arrays.asList(
                new BasicDBObject(
                    "$eq", Arrays.asList("$awards.status", Award.Status.active.toString())),
                "$tender.value.amount",
                0)));
    project.putAll(filterProjectMap);

    DBObject group1 = new BasicDBObject();
    group1.put(Fields.UNDERSCORE_ID, Fields.UNDERSCORE_ID_REF);
    group1.put("year", new BasicDBObject("$first", "$year"));
    group1.put("tenderWithAwards", new BasicDBObject("$max", "$tenderWithAwards"));
    group1.put("tenderWithAwardsValue", new BasicDBObject("$max", "$tenderWithAwardsValue"));
    group1.put("tenderAmount", new BasicDBObject("$first", "$tender.value.amount"));
    filterProjectMap.forEach(
        (k, v) -> group1.put(k.replace(".", ""), new BasicDBObject("$first", "$" + k)));

    DBObject project2 = new BasicDBObject();
    project2.put(Fields.UNDERSCORE_ID, Fields.UNDERSCORE_ID_REF);
    project2.put(Keys.TOTAL_TENDER_AMOUNT, 1);
    project2.put(Keys.TOTAL_TENDERS, 1);
    project2.put(Keys.TOTAL_TENDER_WITH_AWARDS, 1);
    project2.put(
        Keys.PERCENTAGE_TENDERS_WITH_AWARDS,
        new BasicDBObject(
            "$multiply",
            Arrays.asList(
                new BasicDBObject(
                    "$divide", Arrays.asList("$totalTenderWithAwards", "$totalTenders")),
                100)));

    Aggregation agg =
        Aggregation.newAggregation(
            match(
                where("tender.status")
                    .is(Tender.Status.active.toString())
                    .and("tender.tenderPeriod.startDate")
                    .exists(true)
                    .andOperator(
                        getYearDefaultFilterCriteria(filter, "tender.tenderPeriod.startDate"))),
            getMatchDefaultFilterOperation(filter),
            unwind("$awards"),
            new CustomProjectionOperation(project),
            new CustomGroupingOperation(group1),
            getTopXFilterOperation(filter, "$year")
                .sum("tenderWithAwardsValue")
                .as(Keys.TOTAL_TENDER_AMOUNT)
                .count()
                .as(Keys.TOTAL_TENDERS)
                .sum("tenderWithAwards")
                .as(Keys.TOTAL_TENDER_WITH_AWARDS),
            new CustomProjectionOperation(project2),
            filter.getGroupByCategory() != null
                ? sort(Direction.DESC, Keys.TOTAL_TENDER_AMOUNT)
                : sort(Direction.ASC, Fields.UNDERSCORE_ID),
            skip(filter.getSkip()),
            limit(filter.getPageSize()));

    AggregationResults<DBObject> results = mongoTemplate.aggregate(agg, "release", DBObject.class);
    List<DBObject> tagCount = results.getMappedResults();

    return tagCount;
  }