fix test
This commit is contained in:
parent
177606bbbe
commit
cfef7005b3
@ -3,8 +3,7 @@ import { JwtService } from '@nestjs/jwt';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import * as argon2 from 'argon2';
|
||||
import { UserRepository } from '../../domain/ports/out/user.repository';
|
||||
import { User } from '../../domain/entities/user.entity';
|
||||
import { Email } from '../../domain/value-objects/email.vo';
|
||||
import { User, UserRole } from '../../domain/entities/user.entity';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export interface JwtPayload {
|
||||
@ -38,8 +37,7 @@ export class AuthService {
|
||||
this.logger.log(`Registering new user: ${email}`);
|
||||
|
||||
// Check if user already exists
|
||||
const emailVo = Email.create(email);
|
||||
const existingUser = await this.userRepository.findByEmail(emailVo);
|
||||
const existingUser = await this.userRepository.findByEmail(email);
|
||||
|
||||
if (existingUser) {
|
||||
throw new ConflictException('User with this email already exists');
|
||||
@ -57,14 +55,11 @@ export class AuthService {
|
||||
const user = User.create({
|
||||
id: uuidv4(),
|
||||
organizationId,
|
||||
email: emailVo,
|
||||
email,
|
||||
passwordHash,
|
||||
firstName,
|
||||
lastName,
|
||||
role: 'user', // Default role
|
||||
isActive: true,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
role: UserRole.USER, // Default role
|
||||
});
|
||||
|
||||
// Save to database
|
||||
@ -79,7 +74,7 @@ export class AuthService {
|
||||
...tokens,
|
||||
user: {
|
||||
id: savedUser.id,
|
||||
email: savedUser.email.value,
|
||||
email: savedUser.email,
|
||||
firstName: savedUser.firstName,
|
||||
lastName: savedUser.lastName,
|
||||
role: savedUser.role,
|
||||
@ -98,8 +93,7 @@ export class AuthService {
|
||||
this.logger.log(`Login attempt for: ${email}`);
|
||||
|
||||
// Find user by email
|
||||
const emailVo = Email.create(email);
|
||||
const user = await this.userRepository.findByEmail(emailVo);
|
||||
const user = await this.userRepository.findByEmail(email);
|
||||
|
||||
if (!user) {
|
||||
throw new UnauthorizedException('Invalid credentials');
|
||||
@ -125,7 +119,7 @@ export class AuthService {
|
||||
...tokens,
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email.value,
|
||||
email: user.email,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
role: user.role,
|
||||
@ -158,7 +152,7 @@ export class AuthService {
|
||||
// Generate new tokens
|
||||
const tokens = await this.generateTokens(user);
|
||||
|
||||
this.logger.log(`Access token refreshed for user: ${user.email.value}`);
|
||||
this.logger.log(`Access token refreshed for user: ${user.email}`);
|
||||
|
||||
return tokens;
|
||||
} catch (error: any) {
|
||||
@ -186,7 +180,7 @@ export class AuthService {
|
||||
private async generateTokens(user: User): Promise<{ accessToken: string; refreshToken: string }> {
|
||||
const accessPayload: JwtPayload = {
|
||||
sub: user.id,
|
||||
email: user.email.value,
|
||||
email: user.email,
|
||||
role: user.role,
|
||||
organizationId: user.organizationId,
|
||||
type: 'access',
|
||||
@ -194,7 +188,7 @@ export class AuthService {
|
||||
|
||||
const refreshPayload: JwtPayload = {
|
||||
sub: user.id,
|
||||
email: user.email.value,
|
||||
email: user.email,
|
||||
role: user.role,
|
||||
organizationId: user.organizationId,
|
||||
type: 'refresh',
|
||||
|
||||
@ -67,7 +67,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||
// This object will be attached to request.user
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email.value,
|
||||
email: user.email,
|
||||
role: user.role,
|
||||
organizationId: user.organizationId,
|
||||
firstName: user.firstName,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { BookingsController } from '../controllers/bookings.controller';
|
||||
|
||||
// Import domain ports
|
||||
@ -7,6 +8,11 @@ import { RATE_QUOTE_REPOSITORY } from '../../domain/ports/out/rate-quote.reposit
|
||||
import { TypeOrmBookingRepository } from '../../infrastructure/persistence/typeorm/repositories/typeorm-booking.repository';
|
||||
import { TypeOrmRateQuoteRepository } from '../../infrastructure/persistence/typeorm/repositories/typeorm-rate-quote.repository';
|
||||
|
||||
// Import ORM entities
|
||||
import { BookingOrmEntity } from '../../infrastructure/persistence/typeorm/entities/booking.orm-entity';
|
||||
import { ContainerOrmEntity } from '../../infrastructure/persistence/typeorm/entities/container.orm-entity';
|
||||
import { RateQuoteOrmEntity } from '../../infrastructure/persistence/typeorm/entities/rate-quote.orm-entity';
|
||||
|
||||
/**
|
||||
* Bookings Module
|
||||
*
|
||||
@ -17,6 +23,9 @@ import { TypeOrmRateQuoteRepository } from '../../infrastructure/persistence/typ
|
||||
* - Update booking status
|
||||
*/
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([BookingOrmEntity, ContainerOrmEntity, RateQuoteOrmEntity]),
|
||||
],
|
||||
controllers: [BookingsController],
|
||||
providers: [
|
||||
{
|
||||
@ -28,6 +37,6 @@ import { TypeOrmRateQuoteRepository } from '../../infrastructure/persistence/typ
|
||||
useClass: TypeOrmRateQuoteRepository,
|
||||
},
|
||||
],
|
||||
exports: [],
|
||||
exports: [BOOKING_REPOSITORY],
|
||||
})
|
||||
export class BookingsModule {}
|
||||
|
||||
@ -150,10 +150,10 @@ export class AuthController {
|
||||
async refresh(
|
||||
@Body() dto: RefreshTokenDto,
|
||||
): Promise<{ accessToken: string }> {
|
||||
const accessToken =
|
||||
const result =
|
||||
await this.authService.refreshAccessToken(dto.refreshToken);
|
||||
|
||||
return { accessToken };
|
||||
return { accessToken: result.accessToken };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -39,8 +39,7 @@ import {
|
||||
} from '../dto/user.dto';
|
||||
import { UserMapper } from '../mappers/user.mapper';
|
||||
import { UserRepository } from '../../domain/ports/out/user.repository';
|
||||
import { User } from '../../domain/entities/user.entity';
|
||||
import { Email } from '../../domain/value-objects/email.vo';
|
||||
import { User, UserRole as DomainUserRole } from '../../domain/entities/user.entity';
|
||||
import { JwtAuthGuard } from '../guards/jwt-auth.guard';
|
||||
import { RolesGuard } from '../guards/roles.guard';
|
||||
import { CurrentUser, UserPayload } from '../decorators/current-user.decorator';
|
||||
@ -116,8 +115,7 @@ export class UsersController {
|
||||
}
|
||||
|
||||
// Check if user already exists
|
||||
const emailVo = Email.create(dto.email);
|
||||
const existingUser = await this.userRepository.findByEmail(emailVo);
|
||||
const existingUser = await this.userRepository.findByEmail(dto.email);
|
||||
if (existingUser) {
|
||||
throw new ConflictException('User with this email already exists');
|
||||
}
|
||||
@ -134,18 +132,18 @@ export class UsersController {
|
||||
parallelism: 4,
|
||||
});
|
||||
|
||||
// Map DTO role to Domain role
|
||||
const domainRole = dto.role as unknown as DomainUserRole;
|
||||
|
||||
// Create user entity
|
||||
const newUser = User.create({
|
||||
id: uuidv4(),
|
||||
organizationId: dto.organizationId,
|
||||
email: emailVo,
|
||||
email: dto.email,
|
||||
passwordHash,
|
||||
firstName: dto.firstName,
|
||||
lastName: dto.lastName,
|
||||
role: dto.role,
|
||||
isActive: true,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
role: domainRole,
|
||||
});
|
||||
|
||||
// Save to database
|
||||
@ -264,7 +262,8 @@ export class UsersController {
|
||||
}
|
||||
|
||||
if (dto.role) {
|
||||
user.updateRole(dto.role);
|
||||
const domainRole = dto.role as unknown as DomainUserRole;
|
||||
user.updateRole(domainRole);
|
||||
}
|
||||
|
||||
if (dto.isActive !== undefined) {
|
||||
|
||||
@ -13,7 +13,7 @@ export class UserMapper {
|
||||
static toDto(user: User): UserResponseDto {
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email.value,
|
||||
email: user.email,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
role: user.role as any,
|
||||
|
||||
@ -11,10 +11,10 @@
|
||||
*/
|
||||
|
||||
export enum UserRole {
|
||||
ADMIN = 'ADMIN', // Full system access
|
||||
MANAGER = 'MANAGER', // Manage bookings and users within organization
|
||||
USER = 'USER', // Create and view bookings
|
||||
VIEWER = 'VIEWER', // Read-only access
|
||||
ADMIN = 'admin', // Full system access
|
||||
MANAGER = 'manager', // Manage bookings and users within organization
|
||||
USER = 'user', // Create and view bookings
|
||||
VIEWER = 'viewer', // Read-only access
|
||||
}
|
||||
|
||||
export interface UserProps {
|
||||
@ -182,6 +182,22 @@ export class User {
|
||||
this.props.updatedAt = new Date();
|
||||
}
|
||||
|
||||
updateFirstName(firstName: string): void {
|
||||
if (!firstName || firstName.trim().length === 0) {
|
||||
throw new Error('First name cannot be empty.');
|
||||
}
|
||||
this.props.firstName = firstName.trim();
|
||||
this.props.updatedAt = new Date();
|
||||
}
|
||||
|
||||
updateLastName(lastName: string): void {
|
||||
if (!lastName || lastName.trim().length === 0) {
|
||||
throw new Error('Last name cannot be empty.');
|
||||
}
|
||||
this.props.lastName = lastName.trim();
|
||||
this.props.updatedAt = new Date();
|
||||
}
|
||||
|
||||
updateProfile(firstName: string, lastName: string, phoneNumber?: string): void {
|
||||
if (!firstName || firstName.trim().length === 0) {
|
||||
throw new Error('First name cannot be empty.');
|
||||
|
||||
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Booking ORM Entity (Infrastructure Layer)
|
||||
*
|
||||
* TypeORM entity for booking persistence
|
||||
*/
|
||||
|
||||
import {
|
||||
Entity,
|
||||
Column,
|
||||
PrimaryColumn,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
Index,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
JoinColumn,
|
||||
} from 'typeorm';
|
||||
import { UserOrmEntity } from './user.orm-entity';
|
||||
import { OrganizationOrmEntity } from './organization.orm-entity';
|
||||
import { ContainerOrmEntity } from './container.orm-entity';
|
||||
|
||||
/**
|
||||
* Address stored as JSON
|
||||
*/
|
||||
export interface AddressJson {
|
||||
street: string;
|
||||
city: string;
|
||||
postalCode: string;
|
||||
country: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Party (shipper/consignee) stored as JSON
|
||||
*/
|
||||
export interface PartyJson {
|
||||
name: string;
|
||||
address: AddressJson;
|
||||
contactName: string;
|
||||
contactEmail: string;
|
||||
contactPhone: string;
|
||||
}
|
||||
|
||||
@Entity('bookings')
|
||||
@Index('idx_bookings_booking_number', ['bookingNumber'], { unique: true })
|
||||
@Index('idx_bookings_user', ['userId'])
|
||||
@Index('idx_bookings_organization', ['organizationId'])
|
||||
@Index('idx_bookings_rate_quote', ['rateQuoteId'])
|
||||
@Index('idx_bookings_status', ['status'])
|
||||
@Index('idx_bookings_created_at', ['createdAt'])
|
||||
export class BookingOrmEntity {
|
||||
@PrimaryColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ name: 'booking_number', type: 'varchar', length: 20, unique: true })
|
||||
bookingNumber: string;
|
||||
|
||||
@Column({ name: 'user_id', type: 'uuid' })
|
||||
userId: string;
|
||||
|
||||
@ManyToOne(() => UserOrmEntity, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'user_id' })
|
||||
user: UserOrmEntity;
|
||||
|
||||
@Column({ name: 'organization_id', type: 'uuid' })
|
||||
organizationId: string;
|
||||
|
||||
@ManyToOne(() => OrganizationOrmEntity, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'organization_id' })
|
||||
organization: OrganizationOrmEntity;
|
||||
|
||||
@Column({ name: 'rate_quote_id', type: 'uuid' })
|
||||
rateQuoteId: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 50 })
|
||||
status: string;
|
||||
|
||||
@Column({ type: 'jsonb' })
|
||||
shipper: PartyJson;
|
||||
|
||||
@Column({ type: 'jsonb' })
|
||||
consignee: PartyJson;
|
||||
|
||||
@Column({ name: 'cargo_description', type: 'text' })
|
||||
cargoDescription: string;
|
||||
|
||||
@OneToMany(() => ContainerOrmEntity, (container) => container.booking, {
|
||||
cascade: true,
|
||||
eager: true,
|
||||
})
|
||||
containers: ContainerOrmEntity[];
|
||||
|
||||
@Column({ name: 'special_instructions', type: 'text', nullable: true })
|
||||
specialInstructions: string | null;
|
||||
|
||||
@CreateDateColumn({ name: 'created_at' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ name: 'updated_at' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Container ORM Entity (Infrastructure Layer)
|
||||
*
|
||||
* TypeORM entity for container persistence
|
||||
*/
|
||||
|
||||
import {
|
||||
Entity,
|
||||
Column,
|
||||
PrimaryColumn,
|
||||
ManyToOne,
|
||||
JoinColumn,
|
||||
Index,
|
||||
} from 'typeorm';
|
||||
import { BookingOrmEntity } from './booking.orm-entity';
|
||||
|
||||
@Entity('containers')
|
||||
@Index('idx_containers_booking', ['bookingId'])
|
||||
@Index('idx_containers_container_number', ['containerNumber'])
|
||||
export class ContainerOrmEntity {
|
||||
@PrimaryColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ name: 'booking_id', type: 'uuid' })
|
||||
bookingId: string;
|
||||
|
||||
@ManyToOne(() => BookingOrmEntity, (booking) => booking.containers, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn({ name: 'booking_id' })
|
||||
booking: BookingOrmEntity;
|
||||
|
||||
@Column({ type: 'varchar', length: 50 })
|
||||
type: string;
|
||||
|
||||
@Column({ name: 'container_number', type: 'varchar', length: 20, nullable: true })
|
||||
containerNumber: string | null;
|
||||
|
||||
@Column({ type: 'decimal', precision: 10, scale: 2, nullable: true })
|
||||
vgm: number | null;
|
||||
|
||||
@Column({ type: 'decimal', precision: 5, scale: 2, nullable: true })
|
||||
temperature: number | null;
|
||||
|
||||
@Column({ name: 'seal_number', type: 'varchar', length: 50, nullable: true })
|
||||
sealNumber: string | null;
|
||||
}
|
||||
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Booking ORM Mapper
|
||||
*
|
||||
* Maps between Booking domain entity and BookingOrmEntity
|
||||
*/
|
||||
|
||||
import {
|
||||
Booking,
|
||||
BookingProps,
|
||||
Party,
|
||||
BookingContainer,
|
||||
} from '../../../../domain/entities/booking.entity';
|
||||
import { BookingNumber } from '../../../../domain/value-objects/booking-number.vo';
|
||||
import { BookingStatus } from '../../../../domain/value-objects/booking-status.vo';
|
||||
import {
|
||||
BookingOrmEntity,
|
||||
PartyJson,
|
||||
} from '../entities/booking.orm-entity';
|
||||
import { ContainerOrmEntity } from '../entities/container.orm-entity';
|
||||
|
||||
export class BookingOrmMapper {
|
||||
/**
|
||||
* Map domain entity to ORM entity
|
||||
*/
|
||||
static toOrm(domain: Booking): BookingOrmEntity {
|
||||
const orm = new BookingOrmEntity();
|
||||
|
||||
orm.id = domain.id;
|
||||
orm.bookingNumber = domain.bookingNumber.value;
|
||||
orm.userId = domain.userId;
|
||||
orm.organizationId = domain.organizationId;
|
||||
orm.rateQuoteId = domain.rateQuoteId;
|
||||
orm.status = domain.status.value;
|
||||
orm.shipper = this.partyToJson(domain.shipper);
|
||||
orm.consignee = this.partyToJson(domain.consignee);
|
||||
orm.cargoDescription = domain.cargoDescription;
|
||||
orm.specialInstructions = domain.specialInstructions || null;
|
||||
orm.createdAt = domain.createdAt;
|
||||
orm.updatedAt = domain.updatedAt;
|
||||
|
||||
// Map containers
|
||||
orm.containers = domain.containers.map((container) =>
|
||||
this.containerToOrm(container, domain.id)
|
||||
);
|
||||
|
||||
return orm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map ORM entity to domain entity
|
||||
*/
|
||||
static toDomain(orm: BookingOrmEntity): Booking {
|
||||
const props: BookingProps = {
|
||||
id: orm.id,
|
||||
bookingNumber: BookingNumber.fromString(orm.bookingNumber),
|
||||
userId: orm.userId,
|
||||
organizationId: orm.organizationId,
|
||||
rateQuoteId: orm.rateQuoteId,
|
||||
status: BookingStatus.create(orm.status as any),
|
||||
shipper: this.jsonToParty(orm.shipper),
|
||||
consignee: this.jsonToParty(orm.consignee),
|
||||
cargoDescription: orm.cargoDescription,
|
||||
containers: orm.containers
|
||||
? orm.containers.map((c) => this.ormToContainer(c))
|
||||
: [],
|
||||
specialInstructions: orm.specialInstructions || undefined,
|
||||
createdAt: orm.createdAt,
|
||||
updatedAt: orm.updatedAt,
|
||||
};
|
||||
|
||||
return Booking.create({
|
||||
...props,
|
||||
bookingNumber: props.bookingNumber,
|
||||
status: props.status,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Map array of ORM entities to domain entities
|
||||
*/
|
||||
static toDomainMany(orms: BookingOrmEntity[]): Booking[] {
|
||||
return orms.map((orm) => this.toDomain(orm));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert domain Party to JSON
|
||||
*/
|
||||
private static partyToJson(party: Party): PartyJson {
|
||||
return {
|
||||
name: party.name,
|
||||
address: {
|
||||
street: party.address.street,
|
||||
city: party.address.city,
|
||||
postalCode: party.address.postalCode,
|
||||
country: party.address.country,
|
||||
},
|
||||
contactName: party.contactName,
|
||||
contactEmail: party.contactEmail,
|
||||
contactPhone: party.contactPhone,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert JSON to domain Party
|
||||
*/
|
||||
private static jsonToParty(json: PartyJson): Party {
|
||||
return {
|
||||
name: json.name,
|
||||
address: {
|
||||
street: json.address.street,
|
||||
city: json.address.city,
|
||||
postalCode: json.address.postalCode,
|
||||
country: json.address.country,
|
||||
},
|
||||
contactName: json.contactName,
|
||||
contactEmail: json.contactEmail,
|
||||
contactPhone: json.contactPhone,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert domain BookingContainer to ORM entity
|
||||
*/
|
||||
private static containerToOrm(
|
||||
container: BookingContainer,
|
||||
bookingId: string
|
||||
): ContainerOrmEntity {
|
||||
const orm = new ContainerOrmEntity();
|
||||
orm.id = container.id;
|
||||
orm.bookingId = bookingId;
|
||||
orm.type = container.type;
|
||||
orm.containerNumber = container.containerNumber || null;
|
||||
orm.vgm = container.vgm || null;
|
||||
orm.temperature = container.temperature || null;
|
||||
orm.sealNumber = container.sealNumber || null;
|
||||
return orm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert ORM entity to domain BookingContainer
|
||||
*/
|
||||
private static ormToContainer(orm: ContainerOrmEntity): BookingContainer {
|
||||
return {
|
||||
id: orm.id,
|
||||
type: orm.type,
|
||||
containerNumber: orm.containerNumber || undefined,
|
||||
vgm: orm.vgm || undefined,
|
||||
temperature: orm.temperature || undefined,
|
||||
sealNumber: orm.sealNumber || undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* TypeORM Booking Repository
|
||||
*
|
||||
* Implements BookingRepository interface using TypeORM
|
||||
*/
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Booking } from '../../../../domain/entities/booking.entity';
|
||||
import { BookingNumber } from '../../../../domain/value-objects/booking-number.vo';
|
||||
import { BookingStatus } from '../../../../domain/value-objects/booking-status.vo';
|
||||
import { BookingRepository } from '../../../../domain/ports/out/booking.repository';
|
||||
import { BookingOrmEntity } from '../entities/booking.orm-entity';
|
||||
import { ContainerOrmEntity } from '../entities/container.orm-entity';
|
||||
import { BookingOrmMapper } from '../mappers/booking-orm.mapper';
|
||||
|
||||
@Injectable()
|
||||
export class TypeOrmBookingRepository implements BookingRepository {
|
||||
constructor(
|
||||
@InjectRepository(BookingOrmEntity)
|
||||
private readonly bookingRepository: Repository<BookingOrmEntity>,
|
||||
@InjectRepository(ContainerOrmEntity)
|
||||
private readonly containerRepository: Repository<ContainerOrmEntity>
|
||||
) {}
|
||||
|
||||
async save(booking: Booking): Promise<Booking> {
|
||||
const orm = BookingOrmMapper.toOrm(booking);
|
||||
const saved = await this.bookingRepository.save(orm);
|
||||
return BookingOrmMapper.toDomain(saved);
|
||||
}
|
||||
|
||||
async findById(id: string): Promise<Booking | null> {
|
||||
const orm = await this.bookingRepository.findOne({
|
||||
where: { id },
|
||||
relations: ['containers'],
|
||||
});
|
||||
return orm ? BookingOrmMapper.toDomain(orm) : null;
|
||||
}
|
||||
|
||||
async findByBookingNumber(bookingNumber: BookingNumber): Promise<Booking | null> {
|
||||
const orm = await this.bookingRepository.findOne({
|
||||
where: { bookingNumber: bookingNumber.value },
|
||||
relations: ['containers'],
|
||||
});
|
||||
return orm ? BookingOrmMapper.toDomain(orm) : null;
|
||||
}
|
||||
|
||||
async findByUser(userId: string): Promise<Booking[]> {
|
||||
const orms = await this.bookingRepository.find({
|
||||
where: { userId },
|
||||
relations: ['containers'],
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
return BookingOrmMapper.toDomainMany(orms);
|
||||
}
|
||||
|
||||
async findByOrganization(organizationId: string): Promise<Booking[]> {
|
||||
const orms = await this.bookingRepository.find({
|
||||
where: { organizationId },
|
||||
relations: ['containers'],
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
return BookingOrmMapper.toDomainMany(orms);
|
||||
}
|
||||
|
||||
async findByStatus(status: BookingStatus): Promise<Booking[]> {
|
||||
const orms = await this.bookingRepository.find({
|
||||
where: { status: status.value },
|
||||
relations: ['containers'],
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
return BookingOrmMapper.toDomainMany(orms);
|
||||
}
|
||||
|
||||
async delete(id: string): Promise<void> {
|
||||
await this.bookingRepository.delete({ id });
|
||||
}
|
||||
}
|
||||
@ -35,13 +35,20 @@ export class TypeOrmOrganizationRepository implements OrganizationRepository {
|
||||
return orm ? OrganizationOrmMapper.toDomain(orm) : null;
|
||||
}
|
||||
|
||||
async findByScac(scac: string): Promise<Organization | null> {
|
||||
async findBySCAC(scac: string): Promise<Organization | null> {
|
||||
const orm = await this.repository.findOne({
|
||||
where: { scac: scac.toUpperCase() },
|
||||
});
|
||||
return orm ? OrganizationOrmMapper.toDomain(orm) : null;
|
||||
}
|
||||
|
||||
async findAll(): Promise<Organization[]> {
|
||||
const orms = await this.repository.find({
|
||||
order: { name: 'ASC' },
|
||||
});
|
||||
return OrganizationOrmMapper.toDomainMany(orms);
|
||||
}
|
||||
|
||||
async findAllActive(): Promise<Organization[]> {
|
||||
const orms = await this.repository.find({
|
||||
where: { isActive: true },
|
||||
|
||||
Loading…
Reference in New Issue
Block a user