add partner and slug into package

This commit is contained in:
ItsMalma
2025-12-01 12:54:45 +07:00
parent f8f130e2f8
commit 786dbe1bb7
7 changed files with 69 additions and 2 deletions

View File

@@ -1,5 +1,6 @@
{ {
"lockfileVersion": 1, "lockfileVersion": 1,
"configVersion": 0,
"workspaces": { "workspaces": {
"": { "": {
"dependencies": { "dependencies": {

View File

@@ -1,4 +1,5 @@
import { PackageDetail } from "@/database/entities/package-detail.entity"; import { PackageDetail } from "@/database/entities/package-detail.entity";
import { Partner } from "@/database/entities/partner.entity";
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 { import {
@@ -6,9 +7,12 @@ import {
Collection, Collection,
Entity, Entity,
Enum, Enum,
ManyToOne,
OneToMany, OneToMany,
PrimaryKey, PrimaryKey,
Property, Property,
Unique,
type Rel,
} from "@mikro-orm/core"; } from "@mikro-orm/core";
@Entity() @Entity()
@@ -16,6 +20,10 @@ export class Package {
@PrimaryKey({ type: "varchar", length: 30 }) @PrimaryKey({ type: "varchar", length: 30 })
id!: string; id!: string;
@Property({ type: "varchar", length: 100 })
@Unique()
slug!: string;
@Property({ type: "varchar", length: 100 }) @Property({ type: "varchar", length: 100 })
name!: string; name!: string;
@@ -31,6 +39,9 @@ export class Package {
@Property({ type: "boolean" }) @Property({ type: "boolean" })
useFastTrain!: boolean; useFastTrain!: boolean;
@ManyToOne(() => Partner)
partner!: Rel<Partner>;
@Property({ @Property({
type: "timestamp", type: "timestamp",
onCreate: () => new Date(), onCreate: () => new Date(),

View File

@@ -142,7 +142,11 @@ export class CityController extends Controller {
} }
const body = parseBodyResult.data; const body = parseBodyResult.data;
const country = await orm.em.findOne(Country, { id: body.country_id }); const country = await orm.em.findOne(
Country,
{ id: body.country_id },
{ populate: ["*"] },
);
if (!country) { if (!country) {
return res.status(404).json({ return res.status(404).json({
data: null, data: null,

View File

@@ -22,6 +22,7 @@ import {
} from "@/database/entities/package-itinerary-widget.entity"; } from "@/database/entities/package-itinerary-widget.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 { Partner } from "@/database/entities/partner.entity";
import { TransportationClass } from "@/database/entities/transportation-class.entity"; import { TransportationClass } from "@/database/entities/transportation-class.entity";
import { AdminPermission } from "@/database/enums/admin-permission.enum"; import { AdminPermission } from "@/database/enums/admin-permission.enum";
import { PackageItineraryWidgetType } from "@/database/enums/package-itinerary-widget-type.enum"; import { PackageItineraryWidgetType } from "@/database/enums/package-itinerary-widget-type.enum";
@@ -39,6 +40,7 @@ import type {
} from "@/modules/package/package.types"; } from "@/modules/package/package.types";
import { wrap } from "@mikro-orm/core"; import { wrap } 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 { ulid } from "ulid"; import { ulid } from "ulid";
export class PackageController extends Controller { export class PackageController extends Controller {
@@ -61,13 +63,29 @@ export class PackageController extends Controller {
Buffer.from(body.thumbnail, "base64"), Buffer.from(body.thumbnail, "base64"),
); );
const partner = await orm.em.findOne(Partner, { id: body.partner_id });
if (!partner) {
return res.status(404).json({
data: null,
errors: [
{
path: "partner_id",
location: "body",
message: "Partner not found.",
},
],
} satisfies ErrorResponse);
}
const package_ = orm.em.create(Package, { const package_ = orm.em.create(Package, {
id: ulid(), id: ulid(),
slug: slugify(body.name),
name: body.name, name: body.name,
type: body.type, type: body.type,
class: body.class, class: body.class,
thumbnail: thumbnailFile.name, thumbnail: thumbnailFile.name,
useFastTrain: body.use_fast_train, useFastTrain: body.use_fast_train,
partner,
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
}); });
@@ -156,10 +174,30 @@ export class PackageController extends Controller {
} }
const body = parseBodyResult.data; const body = parseBodyResult.data;
const partner = await orm.em.findOne(
Partner,
{ id: body.partner_id },
{ populate: ["*"] },
);
if (!partner) {
return res.status(404).json({
data: null,
errors: [
{
path: "partner_id",
location: "body",
message: "Partner not found.",
},
],
} satisfies ErrorResponse);
}
const package_ = await orm.em.findOne( const package_ = await orm.em.findOne(
Package, Package,
{ id: params.id }, { id: params.id },
{ populate: ["*"] }, {
populate: ["*"],
},
); );
if (!package_) { if (!package_) {
return res.status(404).json({ return res.status(404).json({
@@ -179,10 +217,12 @@ export class PackageController extends Controller {
package_.thumbnail, package_.thumbnail,
); );
package_.slug = slugify(body.name);
package_.name = body.name; package_.name = body.name;
package_.type = body.type; package_.type = body.type;
package_.class = body.class; package_.class = body.class;
package_.useFastTrain = body.use_fast_train; package_.useFastTrain = body.use_fast_train;
package_.partner = partner;
package_.updatedAt = new Date(); package_.updatedAt = new Date();
await orm.em.flush(); await orm.em.flush();

View File

@@ -20,11 +20,13 @@ import type {
PackageItineraryWidgetResponse, PackageItineraryWidgetResponse,
PackageResponse, PackageResponse,
} from "@/modules/package/package.types"; } from "@/modules/package/package.types";
import type { PartnerMapper } from "@/modules/partner/partner.mapper";
import type { TransportationMapper } from "@/modules/transportation/transportation.mapper"; import type { TransportationMapper } from "@/modules/transportation/transportation.mapper";
import * as dateFns from "date-fns"; import * as dateFns from "date-fns";
export class PackageMapper { export class PackageMapper {
public constructor( public constructor(
private readonly partnerMapper: PartnerMapper,
private readonly flightMapper: FlightMapper, private readonly flightMapper: FlightMapper,
private readonly hotelMapper: HotelMapper, private readonly hotelMapper: HotelMapper,
private readonly transportationMapper: TransportationMapper, private readonly transportationMapper: TransportationMapper,
@@ -33,11 +35,13 @@ export class PackageMapper {
public mapEntityToResponse(package_: Package): PackageResponse { public mapEntityToResponse(package_: Package): PackageResponse {
return { return {
id: package_.id, id: package_.id,
slug: package_.slug,
name: package_.name, name: package_.name,
type: package_.type, type: package_.type,
class: package_.class, class: package_.class,
thumbnail: package_.thumbnail, thumbnail: package_.thumbnail,
use_fast_train: package_.useFastTrain, use_fast_train: package_.useFastTrain,
partner: this.partnerMapper.mapEntityToResponse(package_.partner),
created_at: package_.createdAt, created_at: package_.createdAt,
updated_at: package_.updatedAt, updated_at: package_.updatedAt,
}; };

View File

@@ -15,6 +15,10 @@ export const packageRequestSchema = z.object({
), ),
thumbnail: z.base64("Must be base64 string.").nonempty("Must not empty."), thumbnail: z.base64("Must be base64 string.").nonempty("Must not empty."),
use_fast_train: z.boolean("Must be boolean."), use_fast_train: z.boolean("Must be boolean."),
partner_id: z
.ulid("Must be ulid string.")
.nonempty("Must not empty.")
.max(30, "Max 30 characters."),
}); });
export const packageDetailRequestSchema = z.object({ export const packageDetailRequestSchema = z.object({

View File

@@ -8,6 +8,7 @@ import type {
packageParamsSchema, packageParamsSchema,
packageRequestSchema, packageRequestSchema,
} from "@/modules/package/package.schemas"; } from "@/modules/package/package.schemas";
import type { PartnerResponse } from "@/modules/partner/partner.types";
import type { TransportationClassResponse } from "@/modules/transportation/transportation.types"; import type { TransportationClassResponse } from "@/modules/transportation/transportation.types";
import z from "zod"; import z from "zod";
@@ -21,11 +22,13 @@ export type PackageDetailParams = z.infer<typeof packageDetailParamsSchema>;
export type PackageResponse = { export type PackageResponse = {
id: string; id: string;
slug: string;
name: string; name: string;
type: PackageType; type: PackageType;
class: PackageClass; class: PackageClass;
thumbnail: string; thumbnail: string;
use_fast_train: boolean; use_fast_train: boolean;
partner: PartnerResponse;
created_at: Date; created_at: Date;
updated_at: Date; updated_at: Date;
}; };