Skip to content

Commit

Permalink
calculate volume percentage by year, fix total plot area sum
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeh committed Mar 15, 2024
1 parent adcfe67 commit 2cb79de
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 67 deletions.
2 changes: 1 addition & 1 deletion api/src/modules/eudr-alerts/alerts.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
Logger,
ServiceUnavailableException,
} from '@nestjs/common';
import { DataSource, SelectQueryBuilder } from 'typeorm';
import { DataSource } from 'typeorm';
import { AlertsOutput } from 'modules/eudr-alerts/dto/alerts-output.dto';
import {
EUDRAlertDatabaseResult,
Expand Down
81 changes: 81 additions & 0 deletions api/src/modules/eudr-alerts/dashboard/dashboard-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { AlertsOutput } from '../dto/alerts-output.dto';

interface VolumeAndPlotByYear {
year: number;
volume: string;
plotName?: string;
geoRegionId?: string | null;
}

export interface AggregatedVoumeAndPlotByYear extends VolumeAndPlotByYear {
percentage?: number;
}

export const aggregateAndCalculatePercentage = (
records: any[],
): AggregatedVoumeAndPlotByYear[] => {
const withGeoRegion: VolumeAndPlotByYear[] = records.filter(
(record: VolumeAndPlotByYear) => record.geoRegionId !== null,
);

// Group and aggregate records for unknown GeoRegions
const withoutGeoRegion: VolumeAndPlotByYear[] = records
.filter((record: VolumeAndPlotByYear) => record.geoRegionId === null)
.reduce<VolumeAndPlotByYear[]>(
(acc: VolumeAndPlotByYear[], { year, volume }) => {
const existingYearRecord: VolumeAndPlotByYear | undefined = acc.find(
(record: VolumeAndPlotByYear) => record.year === year,
);
if (existingYearRecord) {
existingYearRecord.volume = (
parseFloat(existingYearRecord.volume) + parseFloat(volume)
).toString();
} else {
acc.push({ year, volume, plotName: 'Unknown', geoRegionId: null });
}
return acc;
},
[],
);

// Merge records with known and unknown GeoRegions
const combinedRecords: VolumeAndPlotByYear[] = [
...withGeoRegion,
...withoutGeoRegion,
];

// Calculate total volume per year
const yearTotals: { [key: number]: number } = combinedRecords.reduce<{
[key: number]: number;
}>((acc: { [p: number]: number }, { year, volume }) => {
acc[year] = (acc[year] || 0) + parseFloat(volume);
return acc;
}, {});

return combinedRecords.map((record: VolumeAndPlotByYear) => ({
...record,
percentage: (parseFloat(record.volume) / yearTotals[record.year]) * 100,
}));
};

export const groupAlertsByDate = (
alerts: AlertsOutput[],
geoRegionMap: Map<string, any>,
): any[] => {
const alertsByDate: any = alerts.reduce((acc: any, cur: AlertsOutput) => {
const date: string = cur.alertDate.value.toString();
if (!acc[date]) {
acc[date] = [];
}
acc[date].push({
plotName: geoRegionMap.get(cur.geoRegionId)?.plotName,
geoRegionId: cur.geoRegionId,
alertCount: cur.alertCount,
});
return acc;
}, {});
return Object.keys(alertsByDate).map((key) => ({
alertDate: key,
plots: alertsByDate[key],
}));
};
92 changes: 26 additions & 66 deletions api/src/modules/eudr-alerts/dashboard/eudr-dashboard.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import { GeoRegion } from 'modules/geo-regions/geo-region.entity';
import { EUDRDashBoardDetail } from 'modules/eudr-alerts/dashboard/dashboard-detail.types';
import { MaterialsService } from 'modules/materials/materials.service';
import { AdminRegionsService } from 'modules/admin-regions/admin-regions.service';
import {
groupAlertsByDate,
aggregateAndCalculatePercentage,
} from './dashboard-utils';

@Injectable()
export class EudrDashboardService {
Expand Down Expand Up @@ -516,11 +520,13 @@ export class EudrDashboardService {
})
.andWhere('sl.producerId = :supplierId', { supplierId })
.getRawMany();
const totalArea: number = geoRegions.reduce(
(acc: number, cur: any) => acc + parseInt(cur.totalArea ?? 0),
0,
);
const sourcingRecords: SourcingRecord[] = [];

const sourcingRecords: {
year: number;
volume: number;
plotName: string;
geoRegionId: string;
}[] = [];
for (const geoRegion of geoRegions) {
geoRegion.geoRegionId = geoRegion.geoRegionId ?? null;
geoRegion.plotName = geoRegion.plotName ?? 'Unknown';
Expand All @@ -529,7 +535,7 @@ export class EudrDashboardService {
plotName: geoRegion.plotName,
});
}
const queryBuilder = manager
const queryBuilder: SelectQueryBuilder<any> = manager
.createQueryBuilder(SourcingRecord, 'sr')
.leftJoin(SourcingLocation, 'sl', 'sr.sourcingLocationId = sl.id')
.leftJoin(GeoRegion, 'gr', 'gr.id = sl.geoRegionId');
Expand All @@ -552,13 +558,22 @@ export class EudrDashboardService {
'gr.id as "geoRegionId"',
]);

const newSourcingRecords: any[] = await queryBuilder.getRawMany();
const newSourcingRecords: {
year: number;
volume: number;
plotName: string;
geoRegionId: string;
}[] = await queryBuilder.getRawMany();

sourcingRecords.push(...newSourcingRecords);
}

const totalVolume: number = sourcingRecords.reduce(
(acc: number, cur: any) => acc + parseInt(cur.volume),
(acc: number, cur: any) => acc + parseFloat(cur.volume),
0,
);
const totalArea: number = geoRegions.reduce(
(acc: number, cur: any) => acc + parseFloat(cur.totalArea ?? 0),
0,
);

Expand All @@ -570,15 +585,9 @@ export class EudrDashboardService {
percentage: (geoRegion.totalArea / totalArea) * 100,
area: geoRegion.totalArea,
}));
sourcingInformation.byVolume = aggregateUnknownGeoRegionVolumeValues(
sourcingRecords,
).map((record: any) => ({
plotName: record.plotName,
geoRegionId: record.geoRegionId,
year: record.year,
percentage: (parseInt(record.volume) / totalVolume) * 100,
volume: parseInt(record.volume),
}));

sourcingInformation.byVolume =
aggregateAndCalculatePercentage(sourcingRecords);
}

const alertsOutput: AlertsOutput[] = await this.eudrRepository.getAlerts({
Expand All @@ -601,12 +610,6 @@ export class EudrDashboardService {
startAlertDate: startAlertDate,
endAlertDate: endAlertDate,
totalAlerts,
// values: alertsOutput.map((alert: AlertsOutput) => ({
// alertDate: alert.alertDate.value,
// geoRegionId: alert.geoRegionId,
// alertCount: alert.alertCount || null,
// plotName: geoRegionMap.get(alert.geoRegionId)?.plotName,
// })),
values: groupAlertsByDate(alertsOutput, geoRegionMap),
};

Expand All @@ -616,46 +619,3 @@ export class EudrDashboardService {
});
}
}

const aggregateUnknownGeoRegionVolumeValues = (arr: any[]): any[] => {
const finalRecords = arr.filter((record) => record.geoRegionId !== null);

arr.forEach((record) => {
if (record.geoRegionId === null) {
const existingRecord = finalRecords.find(
(r) => r.year === record.year && r.geoRegionId === null,
);
if (existingRecord) {
existingRecord.plotName = 'Unknown';
existingRecord.volume = (
parseFloat(existingRecord.volume) + parseFloat(record.volume)
).toString();
} else {
finalRecords.push({ ...record });
}
}
});
return finalRecords;
};

const groupAlertsByDate = (
alerts: AlertsOutput[],
geoRegionMap: Map<string, any>,
): any[] => {
const alertsByDate: any = alerts.reduce((acc: any, cur: AlertsOutput) => {
const date: string = cur.alertDate.value.toString();
if (!acc[date]) {
acc[date] = [];
}
acc[date].push({
plotName: geoRegionMap.get(cur.geoRegionId)?.plotName,
geoRegionId: cur.geoRegionId,
alertCount: cur.alertCount,
});
return acc;
}, {});
return Object.keys(alertsByDate).map((key) => ({
alertDate: key,
plots: alertsByDate[key],
}));
};

0 comments on commit 2cb79de

Please sign in to comment.