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) ); return releaseAgg(agg); }  @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") List<Document> fundingByTenderDeliveryLocation(
            @ModelAttribute @Valid final YearFilterPagingRequest filter); @ApiOperation("Calculates percentage of releases with tender with at least one specified delivery location," + " that is the array tender.items.deliveryLocation has to have items." + "Filters out stub tenders, therefore tender.tenderPeriod.startDate has to exist.") @RequestMapping(value = "/api/qualityFundingByTenderDeliveryLocation", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json") List<Document> qualityFundingByTenderDeliveryLocation(
            @ModelAttribute @Valid final YearFilterPagingRequest filter);  }
@Test public void fundingByTenderDeliveryLocation() throws Exception { final List<Document> fundingByTenderDeliveryLocation = fundingByLocationController .fundingByTenderDeliveryLocation(new YearFilterPagingRequest()); final Document first = fundingByTenderDeliveryLocation.get(0); int year = (int) first.get(FundingByLocationController.Keys.YEAR); BasicDBObject deliveryLocation = (BasicDBObject) first .get(FundingByLocationController.Keys.ITEMS_DELIVERY_LOCATION); BasicDBObject geometry = (BasicDBObject) deliveryLocation.get("geometry"); String geometryType = (String) geometry.get("type"); List<Double> coordinates = (List<Double>) geometry.get("coordinates"); double totalTendersAmount = (double) first.get(FundingByLocationController.Keys.TOTAL_TENDERS_AMOUNT); int tendersCount = (int) first.get(FundingByLocationController.Keys.TENDERS_COUNT); Assert.assertEquals(2015, year); Assert.assertEquals("Point", geometryType); Assert.assertEquals(new ArrayList<>(Arrays.asList(45.9432, 24.9668)), coordinates); Assert.assertEquals(9000.0, totalTendersAmount, 0); Assert.assertEquals(1, tendersCount); }