api/src/modules/geo-coding/strategies/point-of-production.geocoding.service.ts
import { Injectable, Logger } from '@nestjs/common';
import { SourcingData } from 'modules/import-data/sourcing-data/dto-processor.service';
import { BaseStrategy } from 'modules/geo-coding/strategies/base-strategy';
import { GeocodeResponse } from 'modules/geo-coding/geocoders/geocoder.interface';
import { SourcingLocation } from 'modules/sourcing-locations/sourcing-location.entity';
@Injectable()
export class PointOfProductionGeocodingStrategy extends BaseStrategy {
logger: Logger = new Logger(PointOfProductionGeocodingStrategy.name);
async geoCodePointOfProduction(sourcingData: SourcingData): Promise<any> {
if (!sourcingData.locationCountryInput)
throw new Error(
'A country must be provided for Point of Production location type',
);
if (this.hasBothAddressAndCoordinates(sourcingData))
throw new Error(
`For ${sourcingData.locationCountryInput} coordinates ${sourcingData.locationLatitude} ,${sourcingData.locationLongitude} and address ${sourcingData.locationAddressInput} has been provided. Either and address or coordinates can be provided for a Point of Production Location Type`,
);
if (sourcingData.locationLongitude && sourcingData.locationLatitude) {
const geoRegionId: string =
await this.geoRegionService.saveGeoRegionAsPoint({
name: sourcingData.locationCountryInput,
coordinates: {
lat: sourcingData.locationLatitude,
lng: sourcingData.locationLongitude,
},
});
let adminRegionId: string;
try {
adminRegionId = (
await this.adminRegionService.getClosestAdminRegionByCoordinates(
{
lng: sourcingData.locationLongitude,
lat: sourcingData.locationLatitude,
},
sourcingData as SourcingLocation,
)
).adminRegionId;
} catch (e) {
const existingSourcingLocation: SourcingLocation | null =
await this.findExistingSourcingLocationByGeoRegionId(
geoRegionId as unknown as string,
);
if (!existingSourcingLocation) {
await this.geoRegionService.remove(geoRegionId as unknown as string);
}
throw e;
}
return {
...sourcingData,
adminRegionId,
geoRegionId,
};
}
if (
sourcingData.locationAddressInput &&
sourcingData.locationCountryInput
) {
const geoCodeResponseData: {
data: GeocodeResponse;
warning: string | undefined;
} = await this.geoCodeByAddress(
sourcingData.locationAddressInput,
sourcingData.locationCountryInput,
);
const geoRegionId: string =
await this.geoRegionService.saveGeoRegionAsPoint({
name: sourcingData.locationCountryInput,
coordinates: {
lat: geoCodeResponseData.data.results[0].geometry.location.lat,
lng: geoCodeResponseData.data.results[0].geometry.location.lng,
},
});
let adminRegionId: string;
try {
adminRegionId = (
await this.adminRegionService.getClosestAdminRegionByCoordinates(
{
lng: geoCodeResponseData?.data?.results[0]?.geometry.location.lng,
lat: geoCodeResponseData?.data?.results[0]?.geometry.location.lat,
},
sourcingData as SourcingLocation,
)
).adminRegionId;
} catch (e) {
await this.geoRegionService.remove(geoRegionId as unknown as string);
throw e;
}
return {
...sourcingData,
adminRegionId,
geoRegionId,
locationWarning: geoCodeResponseData.warning,
};
}
}
}