Skip to content

Commit

Permalink
Validate CSV shipment uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
jmccollum-woolpert authored Dec 7, 2022
1 parent 314a13e commit a408d45
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1307,7 +1307,23 @@ export class CsvUploadDialogComponent implements OnDestroy, OnInit {
.pipe(
mergeMap((res: any[]) => {
if (this.shipmentFile) {
shipments = this.service.csvToShipments(res[0].data, this.mappingFormShipments.value);
const shipmentsResults = this.service.csvToShipments(
res[0].data,
this.mappingFormShipments.value
);
if (shipmentsResults.some((result) => result.errors.length)) {
shipmentsResults.forEach((result, index) => {
this.validationErrors.push(
...result.errors.map(
(error) =>
`Shipment ${result.shipment.label || ''} at index ${index}: ${error.message}`
)
);
});
throw Error('Shipment validation error');
}

shipments = shipmentsResults.map((result) => result.shipment);
}
if (this.vehicleFile) {
vehicles = this.service.csvToVehicles(res[1].data, this.mappingFormVehicles.value);
Expand Down Expand Up @@ -1353,7 +1369,12 @@ export class CsvUploadDialogComponent implements OnDestroy, OnInit {
(err) => {
this.isValidatingWithApi = false;
this.errorValidating = true;
this.validationErrors.push(err.error?.error?.message || err.message);

// Throw default error if none have been provided
if (!this.validationErrors) {
this.validationErrors.push(err.error?.error?.message || err.message);
}

this.changeRef.detectChanges();
}
);
Expand Down
7 changes: 5 additions & 2 deletions application/frontend/src/app/core/models/csv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ export const CSV_DATA_LABELS_ABBREVIATED = {
timeToNextStop: 'Time to next stop',
};

export interface GeocodeErrorResponse {
location: string;
export interface ValidationErrorResponse {
error: true;
message?: string;
source?: any;
Expand All @@ -146,6 +145,10 @@ export interface GeocodeErrorResponse {
index?: number;
}

export interface GeocodeErrorResponse extends ValidationErrorResponse {
location: string;
}

export const EXPERIMENTAL_API_FIELDS_VEHICLES = [
'requiredOperatorType1',
'requiredOperatorType2',
Expand Down
30 changes: 28 additions & 2 deletions application/frontend/src/app/core/services/csv.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
IShipment,
IVehicle,
IVehicleOperator,
ValidationErrorResponse,
} from '../models';
import { FileService } from './file.service';
import { GeocodingService } from './geocoding.service';
Expand Down Expand Up @@ -211,7 +212,10 @@ export class CsvService {
});
}

csvToShipments(csvShipments: any[], mapping: { [key: string]: string }): IShipment[] {
csvToShipments(
csvShipments: any[],
mapping: { [key: string]: string }
): { shipment: IShipment; errors: ValidationErrorResponse[] }[] {
return csvShipments.map((shipment) => {
const timeWindows = this.mapToShipmentTimeWindows(shipment, mapping);
const parsedShipment = {
Expand All @@ -228,8 +232,30 @@ export class CsvService {
this.commaSeparatedStringToIntArray
),
};
return parsedShipment;

return {
shipment: parsedShipment,
errors: this.validateShipment(parsedShipment),
};
});
}

private validateShipment(shipment: IShipment): ValidationErrorResponse[] {
const errors = [];
const loadDemandsError = Object.keys(shipment.loadDemands).some((demandKey) => {
const demand = shipment.loadDemands[demandKey];
return !Number.isInteger(Number.parseFloat(demand.amount as string));
});

if (loadDemandsError) {
errors.push({
error: true,
message: 'Shipment contains invalid load demands',
shipment,
});
}

return errors;
}

csvToVehicles(csvVehicles: any[], mapping: { [key: string]: string }): IVehicle[] {
Expand Down

0 comments on commit a408d45

Please sign in to comment.