mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 17:38:12 +00:00
Fix inventory status column
This commit is contained in:
@@ -133,7 +133,7 @@ export class FirstMileService {
|
||||
async create(dto: CreateFirstMileDto): Promise<FirstMile> {
|
||||
return this.firstMileRepository.create({
|
||||
bookingId: dto.bookingId,
|
||||
status: dto.status ?? 'PAYMENT_PENDING',
|
||||
status: dto.status ?? 'READY_TO_TRANSIT',
|
||||
advancedPayment: dto.advancedPayment ?? 0,
|
||||
remainingPayment: dto.remainingPayment ?? 0,
|
||||
estimatedKm: dto.estimatedKm ?? null,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<<<<<<< HEAD
|
||||
import { BadRequestException, Injectable, Logger, NotFoundException } from '@nestjs/common';
|
||||
import { DataSource, FindOptionsWhere } from 'typeorm';
|
||||
=======
|
||||
import { Injectable, Logger, NotFoundException } from '@nestjs/common';
|
||||
import { FindOptionsWhere } from 'typeorm';
|
||||
>>>>>>> 73de29f7c5977827a68865b9cb492a5a2cf1cead
|
||||
|
||||
import { BookingsRepository } from '../bookings/bookings.repository';
|
||||
import { DriversService } from '../drivers/drivers.service';
|
||||
@@ -40,52 +45,15 @@ export class LastMileService {
|
||||
private readonly notificationsService: NotificationsService,
|
||||
) {}
|
||||
|
||||
async acceptBooking(bookingReference: string): Promise<LastMile> {
|
||||
async acceptBooking(bookingReference: string): Promise<LastMile | null> {
|
||||
const booking = await this.bookingsRepository.findByReference(bookingReference);
|
||||
|
||||
if (!booking) {
|
||||
throw new NotFoundException(`Booking ${bookingReference} not found`);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (booking.paymentStatus !== 'PAID') {
|
||||
throw new BadRequestException(
|
||||
`Booking ${bookingReference} is not paid (payment status: ${booking.paymentStatus})`,
|
||||
);
|
||||
}
|
||||
|
||||
if ((booking.tradeDirection ?? '').toUpperCase() !== 'IMPORT') {
|
||||
throw new BadRequestException(`Booking ${bookingReference} is not an import booking`);
|
||||
}
|
||||
|
||||
if (!booking.lastMileDeliveryAddress?.trim()) {
|
||||
throw new BadRequestException(`Booking ${bookingReference} has no last-mile delivery address`);
|
||||
}
|
||||
|
||||
const [eligibleInventory] = await this.dataSource.query(
|
||||
`SELECT inv.id
|
||||
FROM freight.warehouse_inventory inv
|
||||
WHERE inv.booking_id = $1
|
||||
AND inv.deleted_at IS NULL
|
||||
AND inv.status = 'READY_FOR_PICKUP'
|
||||
AND inv.inspection_status = 'PASSED'
|
||||
LIMIT 1`,
|
||||
[booking.id],
|
||||
);
|
||||
if (!eligibleInventory) {
|
||||
throw new BadRequestException(
|
||||
`Booking ${bookingReference} is not eligible for last mile. Import inventory must pass inspection and be READY_FOR_PICKUP.`,
|
||||
);
|
||||
}
|
||||
|
||||
const [existing] = await this.dataSource.query(
|
||||
`SELECT id
|
||||
FROM freight.last_mile
|
||||
WHERE booking_id = $1 AND deleted_at IS NULL
|
||||
LIMIT 1`,
|
||||
[booking.id],
|
||||
);
|
||||
if (existing) {
|
||||
return this.findById(existing.id);
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.create({
|
||||
@@ -94,17 +62,15 @@ export class LastMileService {
|
||||
});
|
||||
}
|
||||
|
||||
async acceptBookingByReference(bookingReference: string): Promise<LastMile> {
|
||||
async acceptBookingByReference(bookingReference: string): Promise<LastMile | null> {
|
||||
const booking = await this.bookingsRepository.findByReference(bookingReference);
|
||||
|
||||
if (!booking) {
|
||||
throw new NotFoundException(`Booking ${bookingReference} not found`);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (booking.paymentStatus !== 'PAID') {
|
||||
throw new BadRequestException(
|
||||
`Booking ${bookingReference} is not paid (payment status: ${booking.paymentStatus})`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.create({
|
||||
@@ -169,7 +135,7 @@ export class LastMileService {
|
||||
async create(dto: CreateLastMileDto): Promise<LastMile> {
|
||||
return this.lastMileRepository.create({
|
||||
bookingId: dto.bookingId,
|
||||
status: dto.status ?? 'PAYMENT_PENDING',
|
||||
status: dto.status ?? 'READY_TO_TRANSIT',
|
||||
advancedPayment: dto.advancedPayment ?? 0,
|
||||
remainingPayment: dto.remainingPayment ?? 0,
|
||||
estimatedKm: dto.estimatedKm ?? null,
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { Injectable, Logger } from "@nestjs/common";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import axios from "axios";
|
||||
import axios, { isAxiosError } from "axios";
|
||||
|
||||
import { NotificationStrategy } from "./notification.strategy";
|
||||
|
||||
@Injectable()
|
||||
export class SmsNotificationStrategy implements NotificationStrategy {
|
||||
private readonly logger = new Logger(SmsNotificationStrategy.name);
|
||||
|
||||
constructor(private readonly configService: ConfigService) {}
|
||||
|
||||
async send(recipient: string, message: string): Promise<boolean> {
|
||||
@@ -13,24 +15,43 @@ export class SmsNotificationStrategy implements NotificationStrategy {
|
||||
this.configService.get<string>("OZIKING_SMS_URL") ??
|
||||
"https://notification-dev.license.aafda.gov.et/api/sms-services/ozeking/sms";
|
||||
|
||||
await axios.post(
|
||||
url,
|
||||
{
|
||||
to: recipient,
|
||||
sourceId: this.configService.get<string>("OZIKING_SOURCE_ID") ?? "EDR",
|
||||
sourceName: this.configService.get<string>("OZIKING_SOURCE_NAME") ?? "EDR Freight",
|
||||
appKey: this.configService.get<string>("OZIKING_APP_KEY") ?? "",
|
||||
text: message,
|
||||
callbackUrl: "",
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
accept: "*/*",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
const appKey = this.configService.get<string>("OZIKING_APP_KEY") ?? "";
|
||||
if (!appKey) {
|
||||
this.logger.warn("OZIKING_APP_KEY is not set — SMS may be rejected by the API");
|
||||
}
|
||||
|
||||
return true;
|
||||
this.logger.debug(`Sending SMS to ${recipient} via ${url}`);
|
||||
|
||||
try {
|
||||
const response = await axios.post(
|
||||
url,
|
||||
{
|
||||
to: recipient,
|
||||
sourceId: this.configService.get<string>("OZIKING_SOURCE_ID") ?? "EDR",
|
||||
sourceName: this.configService.get<string>("OZIKING_SOURCE_NAME") ?? "EDR Freight",
|
||||
appKey,
|
||||
text: message,
|
||||
callbackUrl: "",
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
accept: "*/*",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
this.logger.debug(`SMS API response: ${response.status} ${JSON.stringify(response.data)}`);
|
||||
return true;
|
||||
} catch (err) {
|
||||
if (isAxiosError(err)) {
|
||||
this.logger.error(
|
||||
`SMS API error: ${err.message} | status=${err.response?.status} | body=${JSON.stringify(err.response?.data)}`,
|
||||
);
|
||||
} else {
|
||||
this.logger.error(`SMS send failed: ${String(err)}`);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user