fix package api bug and add some package query

This commit is contained in:
ItsMalma
2025-12-18 07:51:21 +07:00
parent 9ac6e9e3fd
commit d13d9fa158
3 changed files with 75 additions and 21 deletions

View File

@@ -34,6 +34,7 @@ import {
packageDetailParamsSchema, packageDetailParamsSchema,
packageDetailRequestSchema, packageDetailRequestSchema,
packageParamsSchema, packageParamsSchema,
packageQuerySchema,
packageRequestSchema, packageRequestSchema,
} from "@/modules/package/package.schemas"; } from "@/modules/package/package.schemas";
import type { import type {
@@ -41,7 +42,7 @@ import type {
PackageDetailResponse, PackageDetailResponse,
PackageResponse, PackageResponse,
} from "@/modules/package/package.types"; } from "@/modules/package/package.types";
import { wrap } from "@mikro-orm/core"; import { wrap, type OrderDefinition } from "@mikro-orm/core";
import { Router, type Request, type Response } from "express"; import { Router, type Request, type Response } from "express";
import slugify from "slugify"; import slugify from "slugify";
import { ulid } from "ulid"; import { ulid } from "ulid";
@@ -143,7 +144,7 @@ export class PackageController extends Controller {
} }
async list(req: Request, res: Response) { async list(req: Request, res: Response) {
const parseQueryResult = paginationQuerySchema.safeParse(req.query); const parseQueryResult = packageQuerySchema.safeParse(req.query);
if (!parseQueryResult.success) { if (!parseQueryResult.success) {
return this.handleZodError(parseQueryResult.error, res, "query"); return this.handleZodError(parseQueryResult.error, res, "query");
} }
@@ -151,16 +152,45 @@ export class PackageController extends Controller {
const count = await orm.em.count(Package); const count = await orm.em.count(Package);
const packages = await orm.em.find( const orderBy: OrderDefinition<Package> = {};
Package, switch (query.sort_by) {
{}, case "newest":
{ orderBy.createdAt = "DESC";
limit: query.per_page, break;
offset: (query.page - 1) * query.per_page, case "oldest":
orderBy: { createdAt: "DESC" }, orderBy.createdAt = "ASC";
populate: ["*"], break;
}, }
);
let packageQueryBuilder = orm.em
.createQueryBuilder(Package, "_package")
.select(["*"], true)
.distinctOn(["class"])
.limit(query.per_page)
.offset((query.page - 1) * query.per_page)
.leftJoinAndSelect("_package.partner", "_partner");
if ("class" in query && query.class) {
packageQueryBuilder = packageQueryBuilder.where({ class: query.class });
}
if ("by_ideal" in query && query.by_ideal) {
packageQueryBuilder = packageQueryBuilder.where({ class: "by_ideal" });
}
switch (query.sort_by) {
case "newest":
packageQueryBuilder = packageQueryBuilder.orderBy({
"_package.created_at": "DESC",
});
break;
case "oldest":
packageQueryBuilder = packageQueryBuilder.orderBy({
"_package.created_at": "ASC",
});
break;
}
const packages = await packageQueryBuilder.getResultList();
return res.status(200).json({ return res.status(200).json({
data: packages.map(this.mapper.mapEntityToResponse.bind(this.mapper)), data: packages.map(this.mapper.mapEntityToResponse.bind(this.mapper)),
@@ -376,10 +406,9 @@ export class PackageController extends Controller {
} }
let outboundFlightSchedule: FlightSchedule | null = null; let outboundFlightSchedule: FlightSchedule | null = null;
for (const [ for (const [index, outboundFlightId] of body.outbound_flight_ids
index, .toReversed()
outboundFlightId, .entries()) {
] of body.outbound_flight_ids.entries()) {
const outboundFlight = await orm.em.findOne( const outboundFlight = await orm.em.findOne(
FlightClass, FlightClass,
{ id: outboundFlightId }, { id: outboundFlightId },
@@ -954,10 +983,9 @@ export class PackageController extends Controller {
orm.em.remove(outboundFlight); orm.em.remove(outboundFlight);
} }
let outboundFlightSchedule: FlightSchedule | null = null; let outboundFlightSchedule: FlightSchedule | null = null;
for (const [ for (const [index, outboundFlightId] of body.outbound_flight_ids
index, .toReversed()
outboundFlightId, .entries()) {
] of body.outbound_flight_ids.entries()) {
const outboundFlight = await orm.em.findOne( const outboundFlight = await orm.em.findOne(
FlightClass, FlightClass,
{ id: outboundFlightId }, { id: outboundFlightId },

View File

@@ -1,4 +1,4 @@
import { dateSchema } from "@/common/schemas"; import { dateSchema, paginationQuerySchema } 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";
@@ -205,6 +205,29 @@ export const packageDetailRequestSchema = z.object({
), ),
}); });
export const packageQuerySchema = z.intersection(
paginationQuerySchema,
z.intersection(
z.union([
z.object({
class: z
.enum(PackageClass, "Must be either 'silver', 'gold', or 'platinum'.")
.optional(),
}),
z.object({
by_ideal: z
.stringbool("Must be string boolean 'true' or 'false'.")
.optional(),
}),
]),
z.object({
sort_by: z
.enum(["newest", "oldest"], "Must be either 'newest' or 'oldest'.")
.default("newest"),
}),
),
);
export const packageParamsSchema = z.object({ export const packageParamsSchema = z.object({
id: z id: z
.ulid("Must be ulid string.") .ulid("Must be ulid string.")

View File

@@ -6,6 +6,7 @@ import type {
packageDetailParamsSchema, packageDetailParamsSchema,
packageDetailRequestSchema, packageDetailRequestSchema,
packageParamsSchema, packageParamsSchema,
packageQuerySchema,
packageRequestSchema, packageRequestSchema,
} from "@/modules/package/package.schemas"; } from "@/modules/package/package.schemas";
import type { PartnerResponse } from "@/modules/partner/partner.types"; import type { PartnerResponse } from "@/modules/partner/partner.types";
@@ -16,6 +17,8 @@ export type PackageRequest = z.infer<typeof packageRequestSchema>;
export type PackageDetailRequest = z.infer<typeof packageDetailRequestSchema>; export type PackageDetailRequest = z.infer<typeof packageDetailRequestSchema>;
export type PackageQuery = z.infer<typeof packageQuerySchema>;
export type PackageParams = z.infer<typeof packageParamsSchema>; export type PackageParams = z.infer<typeof packageParamsSchema>;
export type PackageDetailParams = z.infer<typeof packageDetailParamsSchema>; export type PackageDetailParams = z.infer<typeof packageDetailParamsSchema>;