remove hotel schedule

This commit is contained in:
ItsMalma
2025-11-30 10:12:56 +07:00
parent c07d09c4e9
commit 66c8d9681a
6 changed files with 58 additions and 188 deletions

View File

@@ -1,36 +0,0 @@
import { Hotel } from "@/database/entities/hotel.entity";
import {
Entity,
ManyToOne,
PrimaryKey,
Property,
type Rel,
} from "@mikro-orm/core";
@Entity()
export class HotelSchedule {
@PrimaryKey({ type: "varchar", length: 30 })
id!: string;
@ManyToOne(() => Hotel)
hotel!: Rel<Hotel>;
@Property({ type: "time" })
checkIn!: string;
@Property({ type: "time" })
checkOut!: string;
@Property({
type: "timestamp",
onCreate: () => new Date(),
})
createdAt!: Date;
@Property({
type: "timestamp",
onCreate: () => new Date(),
onUpdate: () => new Date(),
})
updatedAt!: Date;
}

View File

@@ -1,5 +1,5 @@
import { FlightSchedule } from "@/database/entities/flight-schedule.entity"; import { FlightSchedule } from "@/database/entities/flight-schedule.entity";
import { HotelSchedule } from "@/database/entities/hotel-schedule.entity"; import { Hotel } from "@/database/entities/hotel.entity";
import { PackageItinerary } from "@/database/entities/package-itinerary.entity"; import { PackageItinerary } from "@/database/entities/package-itinerary.entity";
import { Package } from "@/database/entities/package.entity"; import { Package } from "@/database/entities/package.entity";
import { TransportationClass } from "@/database/entities/transportation-class.entity"; import { TransportationClass } from "@/database/entities/transportation-class.entity";
@@ -43,21 +43,21 @@ export class PackageDetail {
}) })
inboundFlight!: Rel<FlightSchedule>; inboundFlight!: Rel<FlightSchedule>;
@ManyToMany(() => HotelSchedule, undefined, { @ManyToMany(() => Hotel, undefined, {
owner: true, owner: true,
cascade: [Cascade.REMOVE], cascade: [Cascade.REMOVE],
}) })
tourHotels = new Collection<HotelSchedule>(this); tourHotels = new Collection<Hotel>(this);
@ManyToOne(() => HotelSchedule, { @ManyToOne(() => Hotel, {
cascade: [Cascade.REMOVE], cascade: [Cascade.REMOVE],
}) })
makkahHotel!: Rel<HotelSchedule>; makkahHotel!: Rel<Hotel>;
@ManyToOne(() => HotelSchedule, { @ManyToOne(() => Hotel, {
cascade: [Cascade.REMOVE], cascade: [Cascade.REMOVE],
}) })
madinahHotel!: Rel<HotelSchedule>; madinahHotel!: Rel<Hotel>;
@ManyToOne(() => TransportationClass) @ManyToOne(() => TransportationClass)
transportation!: Rel<TransportationClass>; transportation!: Rel<TransportationClass>;

View File

@@ -11,7 +11,6 @@ import type {
} from "@/common/types"; } from "@/common/types";
import { FlightClass } from "@/database/entities/flight-class.entity"; import { FlightClass } from "@/database/entities/flight-class.entity";
import { FlightSchedule } from "@/database/entities/flight-schedule.entity"; import { FlightSchedule } from "@/database/entities/flight-schedule.entity";
import { HotelSchedule } from "@/database/entities/hotel-schedule.entity";
import { Hotel } from "@/database/entities/hotel.entity"; import { Hotel } from "@/database/entities/hotel.entity";
import { PackageDetail } from "@/database/entities/package-detail.entity"; import { PackageDetail } from "@/database/entities/package-detail.entity";
import { PackageItineraryDay } from "@/database/entities/package-itinerary-day.entity"; import { PackageItineraryDay } from "@/database/entities/package-itinerary-day.entity";
@@ -382,7 +381,7 @@ export class PackageController extends Controller {
const makkahHotel = await orm.em.findOne( const makkahHotel = await orm.em.findOne(
Hotel, Hotel,
{ {
id: body.makkah_hotel.hotel_id, id: body.makkah_hotel_id,
}, },
{ {
populate: ["*"], populate: ["*"],
@@ -393,26 +392,18 @@ export class PackageController extends Controller {
data: null, data: null,
errors: [ errors: [
{ {
path: "makkah_hotel.hotel_id", path: "makkah_hotel_id",
location: "body", location: "body",
message: "Hotel not found.", message: "Hotel not found.",
}, },
], ],
}); });
} }
const makkahHotelSchedule = orm.em.create(HotelSchedule, {
id: ulid(),
hotel: makkahHotel,
checkIn: `${body.makkah_hotel.check_in.getHours()}:${body.makkah_hotel.check_in.getMinutes()}:00`,
checkOut: `${body.makkah_hotel.check_out.getHours()}:${body.makkah_hotel.check_out.getMinutes()}:00`,
createdAt: new Date(),
updatedAt: new Date(),
});
const madinahHotel = await orm.em.findOne( const madinahHotel = await orm.em.findOne(
Hotel, Hotel,
{ {
id: body.madinah_hotel.hotel_id, id: body.madinah_hotel_id,
}, },
{ {
populate: ["*"], populate: ["*"],
@@ -423,21 +414,13 @@ export class PackageController extends Controller {
data: null, data: null,
errors: [ errors: [
{ {
path: "madinah_hotel.hotel_id", path: "madinah_hotel_id",
location: "body", location: "body",
message: "Hotel not found.", message: "Hotel not found.",
}, },
], ],
}); });
} }
const madinahHotelSchedule = orm.em.create(HotelSchedule, {
id: ulid(),
hotel: madinahHotel,
checkIn: `${body.madinah_hotel.check_in.getHours()}:${body.madinah_hotel.check_in.getMinutes()}:00`,
checkOut: `${body.madinah_hotel.check_out.getHours()}:${body.madinah_hotel.check_out.getMinutes()}:00`,
createdAt: new Date(),
updatedAt: new Date(),
});
const transportationClass = await orm.em.findOne( const transportationClass = await orm.em.findOne(
TransportationClass, TransportationClass,
@@ -604,8 +587,8 @@ export class PackageController extends Controller {
tourFlight: tourFlightSchedule, tourFlight: tourFlightSchedule,
outboundFlight: outboundFlightSchedule, outboundFlight: outboundFlightSchedule,
inboundFlight: inboundFlightSchedule, inboundFlight: inboundFlightSchedule,
makkahHotel: makkahHotelSchedule, makkahHotel: makkahHotel,
madinahHotel: madinahHotelSchedule, madinahHotel: madinahHotel,
transportation: transportationClass, transportation: transportationClass,
quadPrice: body.quad_price, quadPrice: body.quad_price,
triplePrice: body.triple_price, triplePrice: body.triple_price,
@@ -616,22 +599,22 @@ export class PackageController extends Controller {
updatedAt: new Date(), updatedAt: new Date(),
}); });
for (const [index, tourHotel] of (body.tour_hotels ?? []).entries()) { for (const [index, tourHotelId] of (body.tour_hotel_ids ?? []).entries()) {
const tourHotelEntity = await orm.em.findOne( const tourHotel = await orm.em.findOne(
Hotel, Hotel,
{ {
id: tourHotel.hotel_id, id: tourHotelId,
}, },
{ {
populate: ["*"], populate: ["*"],
}, },
); );
if (!tourHotelEntity) { if (!tourHotel) {
return res.status(404).json({ return res.status(404).json({
data: null, data: null,
errors: [ errors: [
{ {
path: `tour_hotels.${index}.hotel_id`, path: `tour_hotel_ids.${index}`,
location: "body", location: "body",
message: "Hotel not found.", message: "Hotel not found.",
}, },
@@ -639,16 +622,7 @@ export class PackageController extends Controller {
}); });
} }
const tourHotelSchedule = orm.em.create(HotelSchedule, { packageDetail.tourHotels.add(tourHotel);
id: ulid(),
hotel: tourHotelEntity,
checkIn: `${tourHotel.check_in.getHours()}:${tourHotel.check_in.getMinutes()}:00`,
checkOut: `${tourHotel.check_out.getHours()}:${tourHotel.check_out.getMinutes()}:00`,
createdAt: new Date(),
updatedAt: new Date(),
});
packageDetail.tourHotels.add(tourHotelSchedule);
} }
await orm.em.flush(); await orm.em.flush();
@@ -964,11 +938,10 @@ export class PackageController extends Controller {
}); });
} }
orm.em.remove(packageDetail.makkahHotel);
const makkahHotel = await orm.em.findOne( const makkahHotel = await orm.em.findOne(
Hotel, Hotel,
{ {
id: body.makkah_hotel.hotel_id, id: body.makkah_hotel_id,
}, },
{ {
populate: ["*"], populate: ["*"],
@@ -979,27 +952,18 @@ export class PackageController extends Controller {
data: null, data: null,
errors: [ errors: [
{ {
path: "makkah_hotel.hotel_id", path: "makkah_hotel_id",
location: "body", location: "body",
message: "Hotel not found.", message: "Hotel not found.",
}, },
], ],
}); });
} }
const makkahHotelSchedule = orm.em.create(HotelSchedule, {
id: ulid(),
hotel: makkahHotel,
checkIn: `${body.makkah_hotel.check_in.getHours()}:${body.makkah_hotel.check_in.getMinutes()}:00`,
checkOut: `${body.makkah_hotel.check_out.getHours()}:${body.makkah_hotel.check_out.getMinutes()}:00`,
createdAt: new Date(),
updatedAt: new Date(),
});
orm.em.remove(packageDetail.madinahHotel);
const madinahHotel = await orm.em.findOne( const madinahHotel = await orm.em.findOne(
Hotel, Hotel,
{ {
id: body.madinah_hotel.hotel_id, id: body.madinah_hotel_id,
}, },
{ {
populate: ["*"], populate: ["*"],
@@ -1010,21 +974,13 @@ export class PackageController extends Controller {
data: null, data: null,
errors: [ errors: [
{ {
path: "madinah_hotel.hotel_id", path: "madinah_hotel_id",
location: "body", location: "body",
message: "Hotel not found.", message: "Hotel not found.",
}, },
], ],
}); });
} }
const madinahHotelSchedule = orm.em.create(HotelSchedule, {
id: ulid(),
hotel: madinahHotel,
checkIn: `${body.madinah_hotel.check_in.getHours()}:${body.madinah_hotel.check_in.getMinutes()}:00`,
checkOut: `${body.madinah_hotel.check_out.getHours()}:${body.madinah_hotel.check_out.getMinutes()}:00`,
createdAt: new Date(),
updatedAt: new Date(),
});
const transportationClass = await orm.em.findOne( const transportationClass = await orm.em.findOne(
TransportationClass, TransportationClass,
@@ -1214,8 +1170,8 @@ export class PackageController extends Controller {
tourFlight: tourFlightSchedule, tourFlight: tourFlightSchedule,
outboundFlight: outboundFlightSchedule, outboundFlight: outboundFlightSchedule,
inboundFlight: inboundFlightSchedule, inboundFlight: inboundFlightSchedule,
makkahHotel: makkahHotelSchedule, makkahHotel: makkahHotel,
madinahHotel: madinahHotelSchedule, madinahHotel: madinahHotel,
transportation: transportationClass, transportation: transportationClass,
quadPrice: body.quad_price, quadPrice: body.quad_price,
triplePrice: body.triple_price, triplePrice: body.triple_price,
@@ -1225,25 +1181,23 @@ export class PackageController extends Controller {
updatedAt: new Date(), updatedAt: new Date(),
}); });
for (const tourHotel of packageDetail.tourHotels) { packageDetail.tourHotels.set([]);
orm.em.remove(tourHotel); for (const [index, tourHotelId] of (body.tour_hotel_ids ?? []).entries()) {
} const tourHotel = await orm.em.findOne(
for (const [index, tourHotel] of (body.tour_hotels ?? []).entries()) {
const tourHotelEntity = await orm.em.findOne(
Hotel, Hotel,
{ {
id: tourHotel.hotel_id, id: tourHotelId,
}, },
{ {
populate: ["*"], populate: ["*"],
}, },
); );
if (!tourHotelEntity) { if (!tourHotel) {
return res.status(404).json({ return res.status(404).json({
data: null, data: null,
errors: [ errors: [
{ {
path: `tour_hotels.${index}.hotel_id`, path: `tour_hotel_ids.${index}`,
location: "body", location: "body",
message: "Hotel not found.", message: "Hotel not found.",
}, },
@@ -1251,16 +1205,7 @@ export class PackageController extends Controller {
}); });
} }
const tourHotelSchedule = orm.em.create(HotelSchedule, { packageDetail.tourHotels.add(tourHotel);
id: ulid(),
hotel: tourHotelEntity,
checkIn: `${tourHotel.check_in.getHours()}:${tourHotel.check_in.getMinutes()}:00`,
checkOut: `${tourHotel.check_out.getHours()}:${tourHotel.check_out.getMinutes()}:00`,
createdAt: new Date(),
updatedAt: new Date(),
});
packageDetail.tourHotels.add(tourHotelSchedule);
} }
await orm.em.flush(); await orm.em.flush();

View File

@@ -1,5 +1,4 @@
import type { FlightSchedule } from "@/database/entities/flight-schedule.entity"; import type { FlightSchedule } from "@/database/entities/flight-schedule.entity";
import type { HotelSchedule } from "@/database/entities/hotel-schedule.entity";
import type { PackageDetail } from "@/database/entities/package-detail.entity"; import type { PackageDetail } from "@/database/entities/package-detail.entity";
import type { PackageItineraryDay } from "@/database/entities/package-itinerary-day.entity"; import type { PackageItineraryDay } from "@/database/entities/package-itinerary-day.entity";
import type { import type {
@@ -16,7 +15,6 @@ import type { FlightClassResponse } from "@/modules/flight/flight.types";
import type { HotelMapper } from "@/modules/hotel/hotel.mapper"; import type { HotelMapper } from "@/modules/hotel/hotel.mapper";
import type { import type {
PackageDetailResponse, PackageDetailResponse,
PackageHotelResponse,
PackageItineraryDayResponse, PackageItineraryDayResponse,
PackageItineraryResponse, PackageItineraryResponse,
PackageItineraryWidgetResponse, PackageItineraryWidgetResponse,
@@ -63,22 +61,6 @@ export class PackageMapper {
return flightClassResponses; return flightClassResponses;
} }
private mapHotelSchedule(hotelSchedule: HotelSchedule): PackageHotelResponse {
const checkIn = dateFns.parse(hotelSchedule.checkIn, "H:mm:ss", new Date());
const checkOut = dateFns.parse(
hotelSchedule.checkOut,
"H:mm:ss",
new Date(),
);
return {
hotel: this.hotelMapper.mapEntityToResponse(hotelSchedule.hotel),
check_in: dateFns.format(checkIn, "HH:mm"),
check_out: dateFns.format(checkOut, "HH:mm"),
};
}
private mapItineraryWidget( private mapItineraryWidget(
packageItineraryWidget: PackageItineraryWidget, packageItineraryWidget: PackageItineraryWidget,
): PackageItineraryWidgetResponse { ): PackageItineraryWidgetResponse {
@@ -174,9 +156,15 @@ export class PackageMapper {
: null, : null,
outbound_flights: this.mapFlightSchedule(packageDetail.outboundFlight), outbound_flights: this.mapFlightSchedule(packageDetail.outboundFlight),
inbound_flights: this.mapFlightSchedule(packageDetail.inboundFlight), inbound_flights: this.mapFlightSchedule(packageDetail.inboundFlight),
tour_hotels: packageDetail.tourHotels.map(this.mapHotelSchedule), tour_hotels: packageDetail.tourHotels.map(
makkah_hotel: this.mapHotelSchedule(packageDetail.makkahHotel), this.hotelMapper.mapEntityToResponse,
madinah_hotel: this.mapHotelSchedule(packageDetail.madinahHotel), ),
makkah_hotel: this.hotelMapper.mapEntityToResponse(
packageDetail.makkahHotel,
),
madinah_hotel: this.hotelMapper.mapEntityToResponse(
packageDetail.madinahHotel,
),
transportation: this.transportationMapper.mapClassEntityToResponse( transportation: this.transportationMapper.mapClassEntityToResponse(
packageDetail.transportation, packageDetail.transportation,
), ),

View File

@@ -1,4 +1,4 @@
import { dateSchema, timeSchema } from "@/common/schemas"; import { dateSchema } from "@/common/schemas";
import { PackageClass } from "@/database/enums/package-class.enum"; import { PackageClass } from "@/database/enums/package-class.enum";
import { PackageType } from "@/database/enums/package-type.enum"; import { PackageType } from "@/database/enums/package-type.enum";
import z from "zod"; import z from "zod";
@@ -47,45 +47,24 @@ export const packageDetailRequestSchema = z.object({
"Must be array.", "Must be array.",
) )
.nonempty("Must not empty."), .nonempty("Must not empty."),
tour_hotels: z tour_hotel_ids: z
.array( .array(
z.object( z
{ .ulid("Must be ulid string.")
hotel_id: z .nonempty("Must not empty.")
.ulid("Must be ulid string.") .max(30, "Max 30 characters."),
.nonempty("Must not empty.")
.max(30, "Max 30 characters."),
check_in: timeSchema,
check_out: timeSchema,
},
"Must be object.",
),
"Must be array.", "Must be array.",
) )
.nonempty("Must not empty.") .nonempty("Must not empty.")
.nullable(), .nullable(),
makkah_hotel: z.object( makkah_hotel_id: z
{ .ulid("Must be ulid string.")
hotel_id: z .nonempty("Must not empty.")
.ulid("Must be ulid string.") .max(30, "Max 30 characters."),
.nonempty("Must not empty.") madinah_hotel_id: z
.max(30, "Max 30 characters."), .ulid("Must be ulid string.")
check_in: timeSchema, .nonempty("Must not empty.")
check_out: timeSchema, .max(30, "Max 30 characters."),
},
"Must be object.",
),
madinah_hotel: z.object(
{
hotel_id: z
.ulid("Must be ulid string.")
.nonempty("Must not empty.")
.max(30, "Max 30 characters."),
check_in: timeSchema,
check_out: timeSchema,
},
"Must be object.",
),
transportation_id: z transportation_id: z
.ulid("Must be ulid string.") .ulid("Must be ulid string.")
.nonempty("Must not empty.") .nonempty("Must not empty.")

View File

@@ -30,12 +30,6 @@ export type PackageResponse = {
updated_at: Date; updated_at: Date;
}; };
export type PackageHotelResponse = {
hotel: HotelResponse;
check_in: string;
check_out: string;
};
export type PackageItineraryWidgetResponse = export type PackageItineraryWidgetResponse =
| { | {
type: "transport"; type: "transport";
@@ -72,9 +66,9 @@ export type PackageDetailResponse = {
tour_flights: FlightClassResponse[] | null; tour_flights: FlightClassResponse[] | null;
outbound_flights: FlightClassResponse[]; outbound_flights: FlightClassResponse[];
inbound_flights: FlightClassResponse[]; inbound_flights: FlightClassResponse[];
tour_hotels: PackageHotelResponse[] | null; tour_hotels: HotelResponse[] | null;
makkah_hotel: PackageHotelResponse; makkah_hotel: HotelResponse;
madinah_hotel: PackageHotelResponse; madinah_hotel: HotelResponse;
transportation: TransportationClassResponse; transportation: TransportationClassResponse;
quad_price: number; quad_price: number;
triple_price: number; triple_price: number;