class FundingByLocationController extends GenericOCDSController {

    @ApiOperation(value = "Total estimated funding (tender.value) grouped by "
            + "tender.items.deliveryLocation and also grouped by year."
            + " The endpoint also returns the count of tenders for each location. "
            + "It responds to all filters. The year is calculated based on tender.tenderPeriod.startDate")
    @RequestMapping(value = "/api/fundingByTenderDeliveryLocation", method = { RequestMethod.POST,
            RequestMethod.GET }, produces = "application/json")
    public List<Document> fundingByTenderDeliveryLocation(
            @ModelAttribute @Valid final YearFilterPagingRequest filter) {

        DBObject project = new BasicDBObject();
        project.put("tender.items.deliveryLocation", 1);
        project.put(MongoConstants.FieldNames.TENDER_VALUE_AMOUNT, 1);
        addYearlyMonthlyProjection(filter, project, ref(MongoConstants.FieldNames.TENDER_PERIOD_START_DATE));

        Aggregation agg = newAggregation(
                match(where("tender").exists(true).and(MongoConstants.FieldNames.TENDER_PERIOD_START_DATE).exists(true)
                        .andOperator(getYearDefaultFilterCriteria(filter,
                                MongoConstants.FieldNames.TENDER_PERIOD_START_DATE))),
                new CustomProjectionOperation(project), unwind("$tender.items"),
                unwind("$tender.items.deliveryLocation"),
                project(getYearlyMonthlyGroupingFields(filter)).and(MongoConstants.FieldNames.TENDER_VALUE_AMOUNT)
                        .as("tenderAmount")
                        .and("tender.items.deliveryLocation").as("deliveryLocation"),
                match(where("deliveryLocation.geometry.coordinates.0").exists(true)),
                group(getYearlyMonthlyGroupingFields(filter, Keys.ITEMS_DELIVERY_LOCATION))
                        .sum("tenderAmount").as(Keys.TOTAL_TENDERS_AMOUNT).count().as(Keys.TENDERS_COUNT),
                getSortByYearMonth(filter)
        // ,skip(filter.getSkip()), limit(filter.getPageSize())
        );

        return releaseAgg(agg);
    }

}