stashing code
This commit is contained in:
179
apps/frontend/src/lib/domains/ticket/domain/controller.ts
Normal file
179
apps/frontend/src/lib/domains/ticket/domain/controller.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
import { AirportsRepository } from "$lib/domains/airport/data/repository";
|
||||
import type {
|
||||
FlightPriceDetails,
|
||||
FlightTicket,
|
||||
TicketSearchPayload,
|
||||
} from "../data/entities";
|
||||
import { TicketRepository } from "../data/repository";
|
||||
import { getError, Logger } from "@pkg/logger";
|
||||
import { env } from "$env/dynamic/private";
|
||||
import { ScrapedTicketsDataSource } from "../data/scrape.data.source";
|
||||
import { db } from "@pkg/db";
|
||||
import { airportsDb } from "@pkg/airports-db";
|
||||
import { ERROR_CODES, type Result } from "@pkg/result";
|
||||
import { DiscountType, type CouponModel } from "@pkg/logic/domains/coupon/data";
|
||||
import { convertAndFormatCurrency } from "$lib/domains/currency/view/currency.vm.svelte";
|
||||
import { AmadeusTicketsAPIDataSource } from "../data/amadeusapi.data.source";
|
||||
import { getRedisInstance } from "$lib/server/redis";
|
||||
|
||||
export class TicketController {
|
||||
private repo: TicketRepository;
|
||||
private airportsRepo: AirportsRepository;
|
||||
private TICKET_SCRAPERS = ["kiwi"];
|
||||
|
||||
constructor(repo: TicketRepository, airportsRepo: AirportsRepository) {
|
||||
this.repo = repo;
|
||||
this.airportsRepo = airportsRepo;
|
||||
}
|
||||
|
||||
async searchAirports(query: string) {
|
||||
return this.airportsRepo.searchAirports(query);
|
||||
}
|
||||
|
||||
async getAirportByCode(query: string) {
|
||||
return this.airportsRepo.getAirportByCode(query);
|
||||
}
|
||||
async searchForTickets(
|
||||
payload: TicketSearchPayload,
|
||||
coupon: CouponModel | undefined,
|
||||
): Promise<Result<FlightTicket[]>> {
|
||||
const result = await this.repo.searchForTickets({
|
||||
sessionId: payload.sessionId,
|
||||
ticketSearchPayload: payload,
|
||||
providers: this.TICKET_SCRAPERS,
|
||||
});
|
||||
|
||||
if (result.error || !result.data) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!coupon) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Logger.info(`Auto-applying coupon ${coupon.code} to all search results`);
|
||||
|
||||
return {
|
||||
data: result.data.map((ticket) => {
|
||||
return this.applyDiscountToTicket(ticket, coupon);
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
private applyDiscountToTicket(
|
||||
ticket: FlightTicket,
|
||||
coupon: CouponModel,
|
||||
): FlightTicket {
|
||||
// Calculate discount amount
|
||||
let discountAmount = 0;
|
||||
|
||||
if (coupon.discountType === DiscountType.PERCENTAGE) {
|
||||
discountAmount =
|
||||
(ticket.priceDetails.displayPrice *
|
||||
Number(coupon.discountValue)) /
|
||||
100;
|
||||
} else {
|
||||
discountAmount = Number(coupon.discountValue);
|
||||
}
|
||||
|
||||
// Apply maximum discount limit if specified
|
||||
if (
|
||||
coupon.maxDiscountAmount &&
|
||||
discountAmount > Number(coupon.maxDiscountAmount)
|
||||
) {
|
||||
discountAmount = Number(coupon.maxDiscountAmount);
|
||||
}
|
||||
|
||||
// Skip if minimum order value is not met
|
||||
if (
|
||||
coupon.minOrderValue &&
|
||||
ticket.priceDetails.displayPrice < Number(coupon.minOrderValue)
|
||||
) {
|
||||
return ticket;
|
||||
}
|
||||
|
||||
// Create a copy of the ticket with the discount applied
|
||||
const discountedTicket = { ...ticket };
|
||||
|
||||
discountedTicket.priceDetails = {
|
||||
...ticket.priceDetails,
|
||||
discountAmount:
|
||||
(ticket.priceDetails.discountAmount || 0) + discountAmount,
|
||||
displayPrice: ticket.priceDetails.displayPrice - discountAmount,
|
||||
appliedCoupon: coupon.code,
|
||||
couponDescription:
|
||||
coupon.description ||
|
||||
`Coupon discount of ${coupon.discountType === DiscountType.PERCENTAGE ? coupon.discountValue + "%" : convertAndFormatCurrency(parseFloat(coupon.discountValue.toString()))}`,
|
||||
};
|
||||
|
||||
return discountedTicket;
|
||||
}
|
||||
|
||||
async cacheTicket(sid: string, payload: FlightTicket) {
|
||||
Logger.info(
|
||||
`Caching ticket for ${sid} | ${payload.departure}:${payload.arrival}`,
|
||||
);
|
||||
const refOIds = payload.refOIds;
|
||||
if (!refOIds) {
|
||||
// In this case we're not going for any of our fancy checkout jazz
|
||||
return this.repo.createTicket(payload, true);
|
||||
}
|
||||
|
||||
const areAnyLive =
|
||||
await this.repo.areCheckoutAlreadyLiveForOrder(refOIds);
|
||||
|
||||
Logger.info(`Any of the OIds has checkout session live ?? ${areAnyLive}`);
|
||||
|
||||
if (areAnyLive) {
|
||||
return {
|
||||
error: getError({
|
||||
code: ERROR_CODES.INTERNAL_SERVER_ERROR,
|
||||
message: "This ticket offer has expired",
|
||||
userHint:
|
||||
"Please select another one or perform search again to fetch latest offers",
|
||||
actionable: false,
|
||||
detail: "Failed to ticket",
|
||||
}),
|
||||
};
|
||||
}
|
||||
Logger.info("nu'uh seems greenlight to make a ticket");
|
||||
return this.repo.createTicket(payload, true);
|
||||
}
|
||||
|
||||
async updateTicketPrices(tid: number, payload: FlightPriceDetails) {
|
||||
return this.repo.updateTicketPrices(tid, payload);
|
||||
}
|
||||
|
||||
async uncacheAndSaveTicket(tid: number) {
|
||||
return this.repo.uncacheAndSaveTicket(tid);
|
||||
}
|
||||
|
||||
async getCheckoutUrlByRefOId(id: number) {
|
||||
return this.repo.getCheckoutUrlByRefOId(id);
|
||||
}
|
||||
|
||||
async setRefOIdsForTicket(tid: number, oids: number[]) {
|
||||
return this.repo.setRefOIdsForTicket(tid, oids);
|
||||
}
|
||||
|
||||
async getTicketById(id: number) {
|
||||
return this.repo.getTicketById(id);
|
||||
}
|
||||
}
|
||||
|
||||
export function getTC() {
|
||||
const ds = new ScrapedTicketsDataSource(
|
||||
env.TICKET_SCRAPER_API_URL,
|
||||
env.API_KEY,
|
||||
);
|
||||
const amadeusApi = new AmadeusTicketsAPIDataSource(
|
||||
env.AMADEUS_API_BASE_URL,
|
||||
env.AMADEUS_API_KEY,
|
||||
env.AMADEUS_API_SECRET,
|
||||
getRedisInstance(),
|
||||
);
|
||||
return new TicketController(
|
||||
new TicketRepository(db, ds, amadeusApi),
|
||||
new AirportsRepository(airportsDb),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user