Added modules for tracking & shipment info

This commit is contained in:
Thom Werring 2024-03-24 14:30:02 +01:00
parent 500f4a88c9
commit 9279438c20
14 changed files with 337 additions and 1 deletions

View File

@ -1,9 +1,34 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ContainerEntity } from '@/entities/container.entity';
import { LiveTrackingEntity } from '@/entities/liveTracking.entity';
import { ShipmentEntity } from '@/entities/shipment.entity';
import { TrackingModule } from './tracking/tracking.module';
import { ShipmentsModule } from './shipments/shipments.module';
@Module({
imports: [],
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 13306,
username: 'root',
password: 'myfreight',
database: 'myfreight',
entities: [ContainerEntity, LiveTrackingEntity, ShipmentEntity],
synchronize: true,
logging: false,
}),
TypeOrmModule.forFeature([
ContainerEntity,
LiveTrackingEntity,
ShipmentEntity,
]),
TrackingModule,
ShipmentsModule,
],
controllers: [AppController],
providers: [AppService],
})

30
src/dtos/container.dto.ts Normal file
View File

@ -0,0 +1,30 @@
import { ApiProperty } from '@nestjs/swagger';
import { ContainerEntity } from '@/entities/container.entity';
import { instanceToPlain, plainToClass } from 'class-transformer';
export class ContainerDto {
@ApiProperty()
id: string;
@ApiProperty()
containerNumber: string;
@ApiProperty()
shipmentId: string;
constructor(entity: ContainerEntity) {
this.id = entity.id;
this.containerNumber = entity.containerNumber;
this.shipmentId = entity.shipmentId;
}
static fromEntity(entity: ContainerEntity): ContainerDto {
const data = instanceToPlain(entity);
return plainToClass(ContainerDto, data);
}
toEntity(): ContainerEntity {
const data = instanceToPlain(this);
return plainToClass(ContainerEntity, data);
}
}

91
src/dtos/shipment.dto.ts Normal file
View File

@ -0,0 +1,91 @@
import { ShipmentEntity } from '@/entities/shipment.entity';
import { ContainerEntity } from '@/entities/container.entity';
import { LiveTrackingEntity } from '@/entities/liveTracking.entity';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class ShipmentContainerDto {
@ApiProperty()
id: string;
@ApiProperty()
containerNumber: string;
constructor(entity: ContainerEntity) {
this.id = entity.id;
this.containerNumber = entity.containerNumber;
}
static bulk(entities: ContainerEntity[]) {
return entities.map((entity) => new ShipmentContainerDto(entity));
}
}
export class ShipmentLiveTrackingDto {
@ApiProperty({
format: 'date-time',
})
createdAt: string;
@ApiProperty()
latitude: number;
@ApiProperty()
longitude: number;
constructor(entity: LiveTrackingEntity) {
this.createdAt = entity.createdAt.toISOString();
this.latitude = entity.latitude;
this.longitude = entity.longitude;
}
}
export class ShipmentDto {
@ApiProperty()
id: string;
@ApiProperty({
format: 'date-time',
})
createdAt: string;
@ApiProperty()
carrierName: string;
@ApiProperty()
originPort: string;
@ApiProperty()
destinationPort: string;
@ApiProperty({
format: 'date-time',
})
departureDate: string;
@ApiProperty({
format: 'date-time',
})
arrivalDateOriginal: string;
@ApiProperty({
format: 'date-time',
})
arrivalDateEstimate: string;
@ApiPropertyOptional({
isArray: true,
type: ShipmentContainerDto,
})
containers: ShipmentContainerDto[] | null;
@ApiPropertyOptional({
type: ShipmentLiveTrackingDto,
})
liveTracking: ShipmentLiveTrackingDto | null;
constructor(entity: ShipmentEntity) {
this.id = entity.id;
this.createdAt = entity.createdAt.toISOString();
this.carrierName = entity.carrierName;
this.originPort = entity.originPort;
this.destinationPort = entity.destinationPort;
this.departureDate = entity.departureDate.toISOString();
this.arrivalDateOriginal = entity.arrivalDateOriginal.toISOString();
this.arrivalDateEstimate = entity.arrivalDateEstimate.toISOString();
this.containers = Array.isArray(entity.containers)
? ShipmentContainerDto.bulk(entity.containers)
: null;
this.liveTracking = null;
}
static bulk(entities: ShipmentEntity[]) {
return entities.map((entity) => new ShipmentDto(entity));
}
}

35
src/dtos/tracking.dto.ts Normal file
View File

@ -0,0 +1,35 @@
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { IsDate, IsNotEmpty } from 'class-validator';
export class TrackingDto {
@ApiProperty()
@IsNotEmpty()
carrierName!: string;
@ApiProperty()
@IsNotEmpty()
destinationUnLoCode!: string;
@ApiProperty({
type: 'string',
format: 'date-time',
})
@Type(() => Date)
@IsDate()
@IsNotEmpty()
departureDate!: Date;
@ApiProperty({
type: 'string',
format: 'date-time',
})
@IsDate()
@IsNotEmpty()
@Type(() => Date)
arrivalDateEstimate!: Date;
@ApiProperty()
@IsNotEmpty()
containerNumber!: string;
}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ShipmentsController } from './shipments.controller';
describe('ShipmentsController', () => {
let controller: ShipmentsController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [ShipmentsController],
}).compile();
controller = module.get<ShipmentsController>(ShipmentsController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

View File

@ -0,0 +1,27 @@
import { Controller, Get } from '@nestjs/common';
import { ShipmentsService } from '@/shipments/shipments.service';
import { ApiExtraModels, ApiOkResponse, getSchemaPath } from '@nestjs/swagger';
import {
ShipmentContainerDto,
ShipmentDto,
ShipmentLiveTrackingDto,
} from '@/dtos/shipment.dto';
@Controller('shipments')
@ApiExtraModels(ShipmentDto, ShipmentContainerDto, ShipmentLiveTrackingDto)
export class ShipmentsController {
constructor(private readonly shipmentsService: ShipmentsService) {}
@Get()
@ApiOkResponse({
description: 'Returns a list of shipments',
schema: {
items: {
$ref: getSchemaPath(ShipmentDto),
},
},
})
getShipments() {
return this.shipmentsService.getShipments();
}
}

View File

@ -0,0 +1,20 @@
import { Module } from '@nestjs/common';
import { ShipmentsController } from './shipments.controller';
import { ShipmentsService } from './shipments.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ContainerEntity } from '@/entities/container.entity';
import { LiveTrackingEntity } from '@/entities/liveTracking.entity';
import { ShipmentEntity } from '@/entities/shipment.entity';
@Module({
imports: [
TypeOrmModule.forFeature([
ContainerEntity,
LiveTrackingEntity,
ShipmentEntity,
]),
],
controllers: [ShipmentsController],
providers: [ShipmentsService],
})
export class ShipmentsModule {}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ShipmentsService } from './shipments.service';
describe('ShipmentsService', () => {
let service: ShipmentsService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ShipmentsService],
}).compile();
service = module.get<ShipmentsService>(ShipmentsService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -0,0 +1,19 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { ShipmentEntity } from '@/entities/shipment.entity';
import { Repository } from 'typeorm';
@Injectable()
export class ShipmentsService {
constructor(
@InjectRepository(ShipmentEntity)
private readonly shipmentRepository: Repository<ShipmentEntity>,
) {}
// @todo add pagination
getShipments() {
return this.shipmentRepository.find({
relations: ['liveTracking', 'containers'],
});
}
}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { TrackingController } from './tracking.controller';
describe('TrackingController', () => {
let controller: TrackingController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [TrackingController],
}).compile();
controller = module.get<TrackingController>(TrackingController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

View File

@ -0,0 +1,4 @@
import { Controller } from '@nestjs/common';
@Controller('tracking')
export class TrackingController {}

View File

@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { TrackingController } from './tracking.controller';
import { TrackingService } from './tracking.service';
@Module({
controllers: [TrackingController],
providers: [TrackingService],
})
export class TrackingModule {}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { TrackingService } from './tracking.service';
describe('TrackingService', () => {
let service: TrackingService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [TrackingService],
}).compile();
service = module.get<TrackingService>(TrackingService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class TrackingService {}