Skip to content

Commit

Permalink
get promotion info (#70)
Browse files Browse the repository at this point in the history
Co-authored-by: NHT <[email protected]>
  • Loading branch information
nfesta2023 and hoangtuan910 authored Mar 13, 2024
1 parent b5cca82 commit cf59d16
Show file tree
Hide file tree
Showing 10 changed files with 395 additions and 2 deletions.
102 changes: 102 additions & 0 deletions src/entity/coupon.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { CouponCreatorType, CouponFilterType, CouponType } from 'src/enum';
import {
Column,
Entity,
PrimaryGeneratedColumn,
CreateDateColumn,
OneToMany,
} from 'typeorm';
import { Restaurant_Coupon } from './restaurant-coupon.entity';
import { SkusCoupon } from './skus-coupon.entity';
import { SysCategoryCoupon } from './sys-category-coupon.entity';

@Entity('Coupon')
export class Coupon {
@PrimaryGeneratedColumn()
public coupon_id: number;

@Column({ type: 'varchar', length: 255, nullable: false, unique: false })
public name: string;

@Column({ type: 'text', nullable: true, unique: false })
public description: string;

@Column({
type: 'enum',
enum: CouponCreatorType,
nullable: false,
unique: false,
})
public creator_type: CouponCreatorType;

@Column({ type: 'int', nullable: false, unique: false })
public creator_id: number;

@Column({ type: 'varchar', length: 10, nullable: false, unique: false })
public coupon_code: string;

@Column({ type: 'int', nullable: false, unique: false })
public discount_value: number;

@Column({ type: 'int', nullable: false, unique: false })
public discount_unit: number;

@Column({ type: 'tinyint', nullable: false, unique: false })
public is_active: number;

@Column({ type: 'bigint', nullable: false, unique: false })
public valid_from: number;

@Column({ type: 'bigint', nullable: false, unique: false })
public valid_until: number;

@Column({ type: 'int', nullable: true, unique: false })
public budget: number;

@Column({ type: 'int', nullable: true, unique: false })
public mininum_order_value: number;

@Column({ type: 'int', nullable: true, unique: false })
public maximum_discount_amount: number;

@Column({ type: 'tinyint', nullable: false, unique: false })
public platform_sponsor_ratio_percentage: number;

@Column({ type: 'bigint', nullable: true, unique: false })
public out_of_budget: number;

@Column({
type: 'enum',
enum: CouponType,
nullable: false,
unique: false,
})
public coupon_type: CouponType;

@Column({
type: 'enum',
enum: CouponFilterType,
nullable: false,
unique: false,
})
public filter_type: CouponFilterType;

@CreateDateColumn({
type: 'datetime',
nullable: false,
unique: false,
default: () => 'CURRENT_TIMESTAMP',
})
public created_at: Date;

//Relationship

@OneToMany(() => Restaurant_Coupon, (resCoup) => resCoup.coupon_obj)
public restaurant_coupon_obj: Restaurant_Coupon[];

@OneToMany(() => SkusCoupon, (coup) => coup.coupon_obj)
public skus_coupon_obj: SkusCoupon[];

@OneToMany(() => SysCategoryCoupon, (coup) => coup.coupon_obj)
public sys_cat_coupon_obj: SysCategoryCoupon[];
}
31 changes: 31 additions & 0 deletions src/entity/restaurant-coupon.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {
Entity,
PrimaryColumn,
CreateDateColumn,
ManyToOne,
JoinColumn,
} from 'typeorm';
import { Coupon } from './coupon.entity';

@Entity('Restaurant_Coupon')
export class Restaurant_Coupon {
@PrimaryColumn()
public coupon_id: number;
@PrimaryColumn()
public restaurant_id: number;
@CreateDateColumn({
type: 'datetime',
nullable: false,
unique: false,
default: () => 'CURRENT_TIMESTAMP',
})
public created_at: Date;

//Relationship
@ManyToOne(() => Coupon, (coupon) => coupon.restaurant_coupon_obj)
@JoinColumn({
name: 'coupon_id',
referencedColumnName: 'coupon_id',
})
public coupon_obj: Coupon;
}
31 changes: 31 additions & 0 deletions src/entity/skus-coupon.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {
Entity,
PrimaryColumn,
CreateDateColumn,
ManyToOne,
JoinColumn,
} from 'typeorm';
import { Coupon } from './coupon.entity';

@Entity('SKUs_coupon')
export class SkusCoupon {
@PrimaryColumn()
public coupon_id: number;
@PrimaryColumn()
public sku_id: number;
@CreateDateColumn({
type: 'datetime',
nullable: false,
unique: false,
default: () => 'CURRENT_TIMESTAMP',
})
public created_at: Date;

//Relationship
@ManyToOne(() => Coupon, (coupon) => coupon.skus_coupon_obj)
@JoinColumn({
name: 'coupon_id',
referencedColumnName: 'coupon_id',
})
public coupon_obj: Coupon;
}
31 changes: 31 additions & 0 deletions src/entity/sys-category-coupon.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {
Entity,
PrimaryColumn,
CreateDateColumn,
ManyToOne,
JoinColumn,
} from 'typeorm';
import { Coupon } from './coupon.entity';

@Entity('Sys_Category_Coupon')
export class SysCategoryCoupon {
@PrimaryColumn()
public coupon_id: number;
@PrimaryColumn()
public sys_category_id: number;
@CreateDateColumn({
type: 'datetime',
nullable: false,
unique: false,
default: () => 'CURRENT_TIMESTAMP',
})
public created_at: Date;

//Relationship
@ManyToOne(() => Coupon, (coupon) => coupon.sys_cat_coupon_obj)
@JoinColumn({
name: 'coupon_id',
referencedColumnName: 'coupon_id',
})
public coupon_obj: Coupon;
}
16 changes: 16 additions & 0 deletions src/enum/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,19 @@ export enum OrderStatus {
PROCESSING = 'PROCESSING',
READY = 'READY',
}

export enum CouponCreatorType {
ADMIN = 'Admin',
RESTAURANT = 'Restaurant',
}

export enum CouponType {
RESTAURANT = 'restaurant',
SYS_CATEGORY = 'system_category',
SKU = 'sku',
}

export enum CouponFilterType {
INCLUDED = 'included',
EXCLUDED = 'excluded',
}
22 changes: 21 additions & 1 deletion src/feature/common/common.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HttpException, Inject, Injectable } from '@nestjs/common';
import { HttpException, Inject, Injectable, Logger } from '@nestjs/common';
import {
AdditionalInfoForSKU,
BasicTasteSelection,
Expand Down Expand Up @@ -44,6 +44,7 @@ import { ManualCutoffTime } from 'src/entity/manual-cutoff-time.entity';

@Injectable()
export class CommonService {
private readonly logger = new Logger(CommonService.name);
constructor(
@Inject('FLAGSMITH_SERVICE') private readonly flagService: FlagsmithService,
@InjectEntityManager() private entityManager: EntityManager,
Expand Down Expand Up @@ -930,4 +931,23 @@ export class CommonService {
//return data after adjusting with time offset and cutoff time config
return startingPointOfLocalToday + cutoffTimeConfig * 60 * 1000;
}

async validateSkuListBelongsToRestaurant(
restaurant_id: number,
sku_ids: number[],
): Promise<boolean> {
const uniqueSkuIds = [...new Set(sku_ids)];
const skus = await this.entityManager
.createQueryBuilder(SKU, 'sku')
.leftJoinAndSelect('sku.menu_item', 'menuItem')
.where('menuItem.restaurant_id = :restaurant_id', { restaurant_id })
.andWhere('sku.sku_id IN (:...uniqueSkuIds)', { uniqueSkuIds })
.getMany();
return skus.length == uniqueSkuIds.length;
}

findOverlapItemOfTwoArrays(arr1: any[], arr2: any[]): any[] {
const overlap = arr1.filter((item) => arr2.includes(item));
return overlap;
} //end of findOverlapItemOfTwoArrays
}
4 changes: 4 additions & 0 deletions src/feature/order/dto/get-coupon-info-request.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class GetCouponInfoRequest {
restaurant_id: number; //Required
sku_ids: number[]; //Required
}
9 changes: 9 additions & 0 deletions src/feature/order/dto/get-coupon-info-response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export class GetCouponInfoResponse {
coupons: CouponInfo[];
}

interface CouponInfo {
coupon_code: string;
name: string;
description: string;
}
61 changes: 61 additions & 0 deletions src/feature/order/order.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import { GetCutleryFeeRequest } from './dto/get-cutlery-fee-request.dto';
import { GetCutleryFeeResponse } from './dto/get-cutlery-fee-response.dto';
import { CommonService } from '../common/common.service';
import { MoneyType } from 'src/type';
import { GetCouponInfoRequest } from './dto/get-coupon-info-request.dto';
import { GetCouponInfoResponse } from './dto/get-coupon-info-response.dto';
import { Coupon } from 'src/entity/coupon.entity';
import { CustomRpcException } from 'src/exceptions/custom-rpc.exception';

@Controller('order')
export class OrderController {
Expand Down Expand Up @@ -81,4 +85,61 @@ export class OrderController {

return result;
}

@MessagePattern({ cmd: 'get_coupon_info' })
@UseFilters(new CustomRpcExceptionFilter())
async getCouponInfo(
data: GetCouponInfoRequest,
): Promise<GetCouponInfoResponse> {
const { restaurant_id, sku_ids } = data;
const result: GetCouponInfoResponse = { coupons: [] };

//Validate restaurant exist
const restaurant =
await this.commonService.getRestaurantById(restaurant_id);
if (!restaurant) {
throw new CustomRpcException(2, 'Restaurant doesnot exist');
}

//Validate SKU list belongs to the restaurant
if (sku_ids.length > 0) {
const isValidSkuList =
await this.commonService.validateSkuListBelongsToRestaurant(
restaurant_id,
sku_ids,
);
if (!isValidSkuList) {
throw new CustomRpcException(
3,
'SKU list doesnot belong to the restaurant',
);
}
}

//Get restaurant coupon
const restaurantCoupons: Coupon[] =
await this.orderService.getCouponInfoWithRestaurntIds([restaurant_id]);

restaurantCoupons.forEach((i) => {
result.coupons.push({
coupon_code: i.coupon_code,
name: i.name,
description: i.description,
});
});

//get sku coupon
const skuCoupons: Coupon[] =
await this.orderService.getCouponInfoWithSkus(sku_ids);

skuCoupons.forEach((i) => {
result.coupons.push({
coupon_code: i.coupon_code,
name: i.name,
description: i.description,
});
});

return result;
}
}
Loading

0 comments on commit cf59d16

Please sign in to comment.