Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ export enum DynamicIndicator {
potentialCasesU9 = 'potential_cases_U9',
potentialCasesU5 = 'potential_cases_U5',
potentialCases65 = 'potential_cases_65',
alertThreshold = 'alert_threshold',
forecastTrigger = 'forecast_trigger',
forecastSeverity = 'forecast_severity',
trigger = 'trigger', // NOTE: this is the front-end layer that is calculated based on forecastTrigger and/or userTrigger
Expand Down Expand Up @@ -40,7 +39,6 @@ export enum StaticIndicator {
populationTotal = 'populationTotal', // TODO: add missing static indicators
}

export const ALERT_THRESHOLD = DynamicIndicator.alertThreshold;
export const FORECAST_SEVERITY = DynamicIndicator.forecastSeverity;
export const FORECAST_TRIGGER = DynamicIndicator.forecastTrigger;
export const TRIGGER = DynamicIndicator.trigger;
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from '../../admin-area-dynamic-data/admin-area-dynamic-data.entity';
import { AdminDataReturnDto } from '../../admin-area-dynamic-data/dto/admin-data-return.dto';
import {
ALERT_THRESHOLD,
DynamicIndicator,
FORECAST_SEVERITY,
FORECAST_TRIGGER,
Expand Down Expand Up @@ -86,15 +85,7 @@ export class EventAreaService {
): number {
// REFACTOR: the TRIGGER layer should not be necessary
if (indicatorName === TRIGGER) {
// return 'alert_threshold' if available otherwise return 1 or 0 based on alert level
const alertThreshold = indicators.find(
({ indicator }) => indicator === ALERT_THRESHOLD,
);
if (alertThreshold) {
return alertThreshold.value;
} else {
return Number(event.alertLevel === AlertLevel.TRIGGER);
}
return Number(event.alertLevel === AlertLevel.TRIGGER);
}

const indicator = indicators.find(
Expand All @@ -118,7 +109,7 @@ export class EventAreaService {
.createQueryBuilder('dynamic')
.select('dynamic."indicator"', 'indicator')
.addSelect(
`CASE WHEN dynamic."indicator" IN ('${ALERT_THRESHOLD}','${FORECAST_SEVERITY}','${FORECAST_TRIGGER}') THEN MAX(value) ELSE SUM(value) END as "value"`, // NOTE: remove 'alert_threshold' after flash-floods pipeline migrated
`CASE WHEN dynamic."indicator" IN ('${FORECAST_SEVERITY}','${FORECAST_TRIGGER}') THEN MAX(value) ELSE SUM(value) END as "value"`,
)
.where(whereFilters)
.groupBy('dynamic."indicator"')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { LeadTime } from '../admin-area-dynamic-data/enum/lead-time.enum';
import { CountryEntity } from '../country/country.entity';
import { DisasterTypeEntity } from '../disaster-type/disaster-type.entity';

// NOTE: this entity is filled directly via /triggers-per-leadtime endpoint for floods only (for all lead times), while for other disaster-types only event starting lead times are filled indirectly as part of /exposure endpoint
// NOTE: this entity is filled directly via /alerts-per-leadtime endpoint for floods only (for all lead times), while for other disaster-types only event starting lead times are filled indirectly as part of /exposure endpoint
// REFACTOR: to either use this for all disaster types or to remove this exception for floods
@Entity('alert-per-lead-time')
export class AlertPerLeadTimeEntity {
Expand Down
20 changes: 0 additions & 20 deletions services/API-service/src/api/event/dto/alert-per-lead-time.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {

import { LeadTime } from '../../admin-area-dynamic-data/enum/lead-time.enum';

// NOTE: new DTO, used by new endpoint
export class AlertPerLeadTimeDto {
@ApiProperty({ example: '7-day' })
@IsNotEmpty()
Expand All @@ -28,22 +27,3 @@ export class AlertPerLeadTimeDto {
@IsBoolean()
public forecastTrigger: boolean;
}

// NOTE: old DTO, used by old endpoint. Remove this when all pipelines migrated.
export class TriggerPerLeadTimeDto {
@ApiProperty({ example: '7-day' })
@IsNotEmpty()
@IsString()
@IsEnum(LeadTime)
public leadTime: LeadTime;

@ApiProperty({ default: false })
@IsNotEmpty()
@IsBoolean()
public triggered: boolean;

@ApiProperty({ default: false })
@IsOptional()
@IsBoolean()
public thresholdReached: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,9 @@ import {
} from 'class-validator';

import alertsPerLeadTime from '../../../scripts/mock-data/floods/UGA/trigger/G5075/alerts-per-lead-time.json';
import triggersPerLeadTime from '../../../scripts/mock-data/floods/UGA/trigger/G5075/triggers-per-lead-time.json';
import { DisasterType } from '../../disaster-type/disaster-type.enum';
import {
AlertPerLeadTimeDto,
TriggerPerLeadTimeDto,
} from './alert-per-lead-time.dto';
import { AlertPerLeadTimeDto } from './alert-per-lead-time.dto';

// NOTE: new DTO, used by new endpoint
export class UploadAlertsPerLeadTimeDto {
@ApiProperty({ example: 'UGA' })
@IsNotEmpty()
Expand Down Expand Up @@ -46,32 +41,3 @@ export class UploadAlertsPerLeadTimeDto {
@IsOptional()
public date: Date;
}

// NOTE: old DTO, used by old endpoint. Remove this when all pipelines migrated.
export class UploadTriggerPerLeadTimeDto {
@ApiProperty({ example: 'UGA' })
@IsNotEmpty()
@IsString()
public countryCodeISO3: string;

@ApiProperty({ example: DisasterType.Floods })
@IsNotEmpty()
@IsEnum(DisasterType)
@IsString()
public disasterType: DisasterType;

@ApiProperty({ example: 'Typhoon name' })
@IsOptional()
@IsString()
public eventName: string;

@ApiProperty({ example: triggersPerLeadTime })
@IsArray()
@ValidateNested()
@Type(() => TriggerPerLeadTimeDto)
public triggersPerLeadTime: TriggerPerLeadTimeDto[];

@ApiProperty({ example: new Date() })
@IsOptional()
public date: Date;
}
22 changes: 1 addition & 21 deletions services/API-service/src/api/event/event.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ import { DisasterType } from '../disaster-type/disaster-type.enum';
import { UserRole } from '../user/user-role.enum';
import { ActivationLogDto } from './dto/event-place-code.dto';
import { LastUploadDateDto } from './dto/last-upload-date.dto';
import {
UploadAlertsPerLeadTimeDto,
UploadTriggerPerLeadTimeDto,
} from './dto/upload-alerts-per-lead-time.dto';
import { UploadAlertsPerLeadTimeDto } from './dto/upload-alerts-per-lead-time.dto';
import { EventService } from './event.service';

@ApiBearerAuth()
Expand Down Expand Up @@ -129,23 +126,6 @@ export class EventController {
);
}

// NOTE: keep this endpoint in until all pipelines migrated to /alerts-per-lead-time
@UseGuards(RolesGuard)
@Roles(UserRole.PipelineUser)
@ApiOperation({
summary:
'[EXTERNALLY USED - PIPELINE] [OLD endpoint] Upload alert data per leadtime',
})
@ApiResponse({ status: 201, description: 'Uploaded alert data per leadtime' })
@Post('triggers-per-leadtime')
public async uploadTriggerPerLeadTime(
@Body() uploadTriggerPerLeadTimeDto: UploadTriggerPerLeadTimeDto,
): Promise<void> {
await this.eventService.convertOldDtoAndUploadAlertPerLeadTime(
uploadTriggerPerLeadTimeDto,
);
}

@UseGuards(RolesGuard)
@Roles(UserRole.PipelineUser)
@ApiOperation({
Expand Down
67 changes: 3 additions & 64 deletions services/API-service/src/api/event/event.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
import { HelperService } from '../../shared/helper.service';
import { AdminAreaEntity } from '../admin-area/admin-area.entity';
import {
ALERT_THRESHOLD,
FORECAST_SEVERITY,
FORECAST_TRIGGER,
} from '../admin-area-dynamic-data/enum/dynamic-indicator.enum';
Expand All @@ -39,10 +38,7 @@ import { AlertPerLeadTimeEntity } from './alert-per-lead-time.entity';
import { AreaForecastDataDto } from './dto/area-forecast-data.dto';
import { ActivationLogDto } from './dto/event-place-code.dto';
import { LastUploadDateDto } from './dto/last-upload-date.dto';
import {
UploadAlertsPerLeadTimeDto,
UploadTriggerPerLeadTimeDto,
} from './dto/upload-alerts-per-lead-time.dto';
import { UploadAlertsPerLeadTimeDto } from './dto/upload-alerts-per-lead-time.dto';
import {
ALERT_LEVEL_RANK,
ALERT_LEVEL_WARNINGS,
Expand Down Expand Up @@ -222,29 +218,6 @@ export class EventService {
return this.helperService.getLastUploadDate(countryCodeISO3, disasterType);
}

// NOTE: remove after all pipelines migrated to new endpoint
public async convertOldDtoAndUploadAlertPerLeadTime(
uploadTriggerPerLeadTimeDto: UploadTriggerPerLeadTimeDto,
) {
const uploadAlertsPerLeadTimeDto = new UploadAlertsPerLeadTimeDto();
uploadAlertsPerLeadTimeDto.countryCodeISO3 =
uploadTriggerPerLeadTimeDto.countryCodeISO3;
uploadAlertsPerLeadTimeDto.disasterType =
uploadTriggerPerLeadTimeDto.disasterType;
uploadAlertsPerLeadTimeDto.eventName =
uploadTriggerPerLeadTimeDto.eventName;
uploadAlertsPerLeadTimeDto.date = uploadAlertsPerLeadTimeDto.date;
uploadAlertsPerLeadTimeDto.alertsPerLeadTime =
uploadTriggerPerLeadTimeDto.triggersPerLeadTime.map((trigger) => {
return {
leadTime: trigger.leadTime,
forecastAlert: trigger.triggered,
forecastTrigger: trigger.thresholdReached,
};
});
await this.uploadAlertsPerLeadTime(uploadAlertsPerLeadTimeDto);
}

public async uploadAlertsPerLeadTime(
uploadAlertsPerLeadTimeDto: UploadAlertsPerLeadTimeDto,
): Promise<AlertPerLeadTimeEntity[]> {
Expand Down Expand Up @@ -813,42 +786,8 @@ export class EventService {
mainExposureValue: area.mainExposureValue,
}));
} else {
// NOTE: remove after all pipelines migrated to new setup
const areasWithAlertThresholdData = await this.adminAreaDynamicDataRepo
.createQueryBuilder('alert')
.select([
'alert.placeCode AS "placeCode"',
'alert.leadTime AS "leadTime"',
'alert.value AS "alertThresholdValue"',
'exposure.value AS "mainExposureValue"',
])
.leftJoin(
AdminAreaDynamicDataEntity,
'exposure',
`alert.placeCode = exposure."placeCode"
AND alert.timestamp = exposure."timestamp"
AND alert.eventName = exposure."eventName"
AND alert.disasterType = exposure."disasterType"
AND alert.leadTime = exposure."leadTime"
AND exposure.indicator = :indicator`,
{ indicator: mainExposureIndicator },
)
.where({ ...whereFilters, indicator: ALERT_THRESHOLD })
.andWhere(
`(alert.value > 0 OR (alert."disasterType" IN ('typhoon','flash-floods')))`, // This reflects the current functionality where alert_threshold=0 for warnings in typhoon and flash-floods
)
.getRawMany();

// TODO: handle situations where also this results in empty array?

return areasWithAlertThresholdData.map((area) => ({
placeCode: area.placeCode,
leadTime: area.leadTime as LeadTime,
forecastSeverity:
area.alertThresholdValue > 0 ? area.alertThresholdValue : 1, // This maps 0-values for typhoon/flash-floods to severity of 1 in the new setup.
forecastTrigger: area.alertThresholdValue === 1, // This reflects current functionality where trigger is equal to alert_threshold=1
mainExposureValue: area.mainExposureValue,
}));
// TODO: this situation should not happen, but check/handle better
return [];
}
}

Expand Down
3 changes: 0 additions & 3 deletions services/API-service/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,3 @@ export const EXTERNAL_API = {
whatsAppStatus: baseApiUrl + API_PATHS.whatsAppStatus,
whatsAppIncoming: baseApiUrl + API_PATHS.whatsAppIncoming,
};

// Set this to true to temporarily test with old pipeline upload. Remove after all pipelines migrated.
export const MOCK_USE_OLD_PIPELINE_UPLOAD = false;

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading