class CostEffectivenessVisualsController extends GenericOCDSController {

    @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<Document> costEffectivenessTenderAmount(
            @ModelAttribute @Valid final GroupingFilterPagingRequest filter) {

        DBObject project = new BasicDBObject();
        project.put("year", new BasicDBObject("$year", ref(MongoConstants.FieldNames.TENDER_PERIOD_START_DATE)));
        addYearlyMonthlyProjection(filter, project, ref(MongoConstants.FieldNames.TENDER_PERIOD_START_DATE));
        project.put(MongoConstants.FieldNames.TENDER_VALUE_AMOUNT, 1);
        project.put(Fields.UNDERSCORE_ID, "$tender._id");
        project.put(
                "tenderWithAwards",
                new BasicDBObject("$cond", Arrays.asList(
                        new BasicDBObject(
                                "$eq", Arrays.asList(
                                ref(MongoConstants.FieldNames.AWARDS_STATUS),
                                Award.Status.active.toString()
                        )), 1,
                        0
                ))
        );
        project.put("tenderWithAwardsValue", new BasicDBObject(
                "$cond",
                Arrays.asList(new BasicDBObject(
                                "$eq", Arrays.asList(ref(MongoConstants.FieldNames.AWARDS_STATUS),
                        Award.Status.active.toString()
                        )),
                        ref(MongoConstants.FieldNames.TENDER_VALUE_AMOUNT), 0
                )
        ));
        project.putAll(filterProjectMap);

        DBObject group1 = new BasicDBObject();
        group1.put(
                Fields.UNDERSCORE_ID, Fields.UNDERSCORE_ID_REF);
        addYearlyMonthlyGroupingOperationFirst(filter, group1);
        group1.put("tenderWithAwards", new BasicDBObject("$max", "$tenderWithAwards"));
        group1.put("tenderWithAwardsValue", new BasicDBObject("$max", "$tenderWithAwardsValue"));
        group1.put("tenderAmount", new BasicDBObject("$first", ref(MongoConstants.FieldNames.TENDER_VALUE_AMOUNT)));
        filterProjectMap.forEach((k, v) ->
                group1.put(
                        k.replace(".", ""),
                        k.equals("tender.items.classification._id")
                                ? new BasicDBObject("$first", new BasicDBObject(
                                "$arrayElemAt",
                                Arrays.asList("$" + k, 0)
                        ))
                                :
                                new BasicDBObject("$first", "$" + k)
                ));

        Aggregation agg = Aggregation.newAggregation(
                match(where(MongoConstants.FieldNames.TENDER_STATUS).is(Tender.Status.active.toString()).
                        and(MongoConstants.FieldNames.TENDER_PERIOD_START_DATE)
                        .exists(true)
                        .andOperator(getYearDefaultFilterCriteria(
                                filter,
                                MongoConstants.FieldNames.TENDER_PERIOD_START_DATE
                        ))),
                getMatchDefaultFilterOperation(filter),
                new CustomUnwindOperation("$awards", true),
                new CustomProjectionOperation(project),
                new CustomGroupingOperation(group1),
                getTopXFilterOperation(filter, getYearlyMonthlyGroupingFields(filter)).sum("tenderWithAwardsValue")
                        .as(Keys.TOTAL_TENDER_AMOUNT).count().as(Keys.TOTAL_TENDERS).sum("tenderWithAwards")
                        .as(Keys.TOTAL_TENDER_WITH_AWARDS),
                project(Keys.TOTAL_TENDER_AMOUNT, Keys.TOTAL_TENDERS, Keys.TOTAL_TENDER_WITH_AWARDS)
                        .andInclude(Fields.from(
                                Fields.field(
                                        Fields.UNDERSCORE_ID, Fields.UNDERSCORE_ID_REF)))
                        .and(Keys.TOTAL_TENDER_WITH_AWARDS).divide(Keys.TOTAL_TENDERS)
                        .as(Keys.FRACTION_TENDERS_WITH_AWARDS),
                project(Keys.TOTAL_TENDER_AMOUNT, Keys.TOTAL_TENDERS, Keys.TOTAL_TENDER_WITH_AWARDS,
                        Fields.UNDERSCORE_ID
                ).and(Keys.FRACTION_TENDERS_WITH_AWARDS).multiply(100)
                        .as(Keys.PERCENTAGE_TENDERS_WITH_AWARDS),
                (filter.getGroupByCategory() == null
                        ? transformYearlyGrouping(filter) : project()).andInclude(Keys.TOTAL_TENDER_AMOUNT,
                        Keys.TOTAL_TENDERS,
                        Keys.TOTAL_TENDER_WITH_AWARDS, Keys.PERCENTAGE_TENDERS_WITH_AWARDS
                ),
                filter.getGroupByCategory() == null
                        ? getSortByYearMonth(filter) : sort(Sort.Direction.DESC, Keys.TOTAL_TENDER_AMOUNT),
                skip(filter.getSkip()), limit(filter.getPageSize())
        )
                .withOptions(Aggregation.newAggregationOptions().allowDiskUse(true).build());

        return releaseAgg(agg);
    }

}