separate flight class api and transportation class api into different module

This commit is contained in:
ItsMalma
2025-11-29 12:06:39 +07:00
parent 1fd90fdeab
commit 84a04da1e6
11 changed files with 271 additions and 74 deletions

View File

@@ -0,0 +1,57 @@
import { Controller } from "@/common/controller";
import { createOrmContextMiddleware } from "@/common/middlewares/create-orm-context.middleware";
import { paginationQuerySchema } from "@/common/schemas";
import type { ListResponse } from "@/common/types";
import { FlightClass } from "@/database/entities/flight-class.entity";
import { Flight } from "@/database/entities/flight.entity";
import { orm } from "@/database/orm";
import type { FlightClassMapper } from "@/modules/flight-class/flight-class.mapper";
import type { FlightClassResponse } from "@/modules/flight-class/flight-class.types";
import { Router, type Request, type Response } from "express";
export class FlightClassController extends Controller {
public constructor(private readonly mapper: FlightClassMapper) {
super();
}
async list(req: Request, res: Response) {
const parseQueryResult = paginationQuerySchema.safeParse(req.query);
if (!parseQueryResult.success) {
return this.handleZodError(parseQueryResult.error, res, "query");
}
const query = parseQueryResult.data;
const count = await orm.em.count(Flight);
const flightClasses = await orm.em.find(
FlightClass,
{},
{
limit: query.per_page,
offset: (query.page - 1) * query.per_page,
orderBy: { createdAt: "DESC" },
populate: ["*"],
},
);
return res.status(200).json({
data: flightClasses.map(
this.mapper.mapEntityToResponse.bind(this.mapper),
),
errors: null,
meta: {
page: query.page,
per_page: query.per_page,
total_pages: Math.ceil(count / query.per_page),
total_items: count,
},
} satisfies ListResponse<FlightClassResponse>);
}
public buildRouter(): Router {
const router = Router();
router.get("/", createOrmContextMiddleware, this.list.bind(this));
return router;
}
}

View File

@@ -0,0 +1,20 @@
import type { FlightClass } from "@/database/entities/flight-class.entity";
import type { FlightMapper } from "@/modules/flight/flight.mapper";
import type { FlightClassResponse } from "@/modules/flight/flight.types";
export class FlightClassMapper {
public constructor(private readonly flightMapper: FlightMapper) {}
public mapEntityToResponse(flightClass: FlightClass): FlightClassResponse {
return {
id: flightClass.id,
flight: this.flightMapper.mapEntityToResponse(flightClass.flight),
class: flightClass.class,
seat_layout: flightClass.seatLayout,
baggage: flightClass.baggage,
cabin_baggage: flightClass.cabinBaggage,
created_at: flightClass.createdAt,
updated_at: flightClass.updatedAt,
};
}
}

View File

@@ -0,0 +1,27 @@
import z from "zod";
export const flightClassRequestSchema = z.object({
class: z
.string("Must be string.")
.nonempty("Must not empty.")
.max(100, "Max 100 characters."),
seat_layout: z
.string("Must be string.")
.nonempty("Must not empty.")
.max(10, "Max 10 characters."),
baggage: z
.number("Must be number.")
.int("Must be integer.")
.positive("Must be positive."),
cabin_baggage: z
.number("Must be number.")
.int("Must be integer.")
.positive("Must be positive."),
});
export const flightClassParamsSchema = z.object({
id: z
.ulid("Must be ulid string.")
.nonempty("Must not empty.")
.max(30, "Max 30 characters."),
});

View File

@@ -0,0 +1,21 @@
import type {
flightClassParamsSchema,
flightClassRequestSchema,
} from "@/modules/flight-class/flight-class.schemas";
import type { FlightResponse } from "@/modules/flight/flight.types";
import z from "zod";
export type FlightClassRequest = z.infer<typeof flightClassRequestSchema>;
export type FlightClassQuery = z.infer<typeof flightClassParamsSchema>;
export type FlightClassResponse = {
id: string;
flight: FlightResponse;
class: string;
seat_layout: string;
baggage: number;
cabin_baggage: number;
created_at: Date;
updated_at: Date;
};