coupon bug

This commit is contained in:
2025-12-07 09:08:33 +03:30
parent f2ae0fe020
commit bc159a983b
10 changed files with 37 additions and 23 deletions
+3 -2
View File
@@ -17,7 +17,7 @@ import { Delivery } from '../../delivery/entities/delivery.entity';
import { Cart, CartItem } from '../interfaces/cart.interface'; import { Cart, CartItem } from '../interfaces/cart.interface';
import { CouponService } from 'src/modules/coupons/providers/coupon.service'; import { CouponService } from 'src/modules/coupons/providers/coupon.service';
import { OrderCouponDetail } from 'src/modules/orders/interface/order-status'; import { OrderCouponDetail } from 'src/modules/orders/interface/order-status';
import { CouponType } from 'src/modules/coupons/entities/coupon.entity'; import { CouponType } from 'src/modules/coupons/interface/coupon';
@Injectable() @Injectable()
export class CartService { export class CartService {
@@ -489,7 +489,8 @@ export class CartService {
*/ */
async setAddress(userId: string, restaurantId: string, setAddressDto: SetAddressDto): Promise<Cart> { async setAddress(userId: string, restaurantId: string, setAddressDto: SetAddressDto): Promise<Cart> {
const cart = await this.findOneOrFail(userId, restaurantId); const cart = await this.findOneOrFail(userId, restaurantId);
if (!cart.deliveryMethodId) throw new BadRequestException('Delivery method must be set before setting address');
// Find and validate address belongs to user // Find and validate address belongs to user
const address = await this.em.findOne(UserAddress, { id: setAddressDto.addressId }, { populate: ['user'] }); const address = await this.em.findOne(UserAddress, { id: setAddressDto.addressId }, { populate: ['user'] });
if (!address) { if (!address) {
@@ -81,6 +81,8 @@ export class CouponController {
return this.couponService.remove(id); return this.couponService.remove(id);
} }
@UseGuards(AdminAuthGuard)
@ApiBearerAuth()
@Get('admin/coupons/generate-code') @Get('admin/coupons/generate-code')
@ApiOperation({ summary: 'generate a coupon code' }) @ApiOperation({ summary: 'generate a coupon code' })
generateCouponCode(@RestId() restId: string) { generateCouponCode(@RestId() restId: string) {
+20 -11
View File
@@ -1,7 +1,17 @@
import { IsNotEmpty, IsString, IsEnum, IsNumber, IsOptional, IsBoolean, IsDateString, Min, IsArray } from 'class-validator'; import {
IsNotEmpty,
IsString,
IsEnum,
IsNumber,
IsOptional,
IsBoolean,
IsDateString,
Min,
IsArray,
} from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer'; import { Type } from 'class-transformer';
import { CouponType } from '../entities/coupon.entity'; import { CouponType } from '../interface/coupon';
export class CreateCouponDto { export class CreateCouponDto {
@IsNotEmpty() @IsNotEmpty()
@@ -78,29 +88,28 @@ export class CreateCouponDto {
@IsOptional() @IsOptional()
@IsArray() @IsArray()
@IsString({ each: true }) @IsString({ each: true })
@ApiPropertyOptional({ @ApiPropertyOptional({
example: ['category-id-1', 'category-id-2'], example: ['category-id-1', 'category-id-2'],
description: 'Array of food category IDs. If empty, coupon applies to all categories.', description: 'Array of food category IDs. If empty, coupon applies to all categories.',
type: [String] type: [String],
}) })
foodCategories?: string[]; foodCategories?: string[];
@IsOptional() @IsOptional()
@IsArray() @IsArray()
@IsString({ each: true }) @IsString({ each: true })
@ApiPropertyOptional({ @ApiPropertyOptional({
example: ['food-id-1', 'food-id-2'], example: ['food-id-1', 'food-id-2'],
description: 'Array of food IDs. If empty, coupon applies to all foods.', description: 'Array of food IDs. If empty, coupon applies to all foods.',
type: [String] type: [String],
}) })
foods?: string[]; foods?: string[];
@IsOptional() @IsOptional()
@IsString() @IsString()
@ApiPropertyOptional({ @ApiPropertyOptional({
example: '09123456789', example: '09123456789',
description: 'Phone number of the user who can use this coupon. If empty, coupon can be used by any user.', description: 'Phone number of the user who can use this coupon. If empty, coupon can be used by any user.',
}) })
userPhone?: string; userPhone?: string;
} }
+1 -1
View File
@@ -1,7 +1,7 @@
import { IsOptional, IsString, IsBoolean, IsNumber, IsEnum } from 'class-validator'; import { IsOptional, IsString, IsBoolean, IsNumber, IsEnum } from 'class-validator';
import { ApiPropertyOptional } from '@nestjs/swagger'; import { ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer'; import { Type } from 'class-transformer';
import { CouponType } from '../entities/coupon.entity'; import { CouponType } from '../interface/coupon';
export class FindCouponsDto { export class FindCouponsDto {
@IsOptional() @IsOptional()
@@ -2,11 +2,7 @@ import { Entity, ManyToOne, Property, Enum, Unique } from '@mikro-orm/core';
import { BaseEntity } from '../../../common/entities/base.entity'; import { BaseEntity } from '../../../common/entities/base.entity';
import { Restaurant } from '../../restaurants/entities/restaurant.entity'; import { Restaurant } from '../../restaurants/entities/restaurant.entity';
import { normalizePhone } from '../../utils/phone.util'; import { normalizePhone } from '../../utils/phone.util';
import { CouponType } from '../interface/coupon';
export enum CouponType {
PERCENTAGE = 'PERCENTAGE',
FIXED = 'FIXED',
}
@Entity({ tableName: 'coupons' }) @Entity({ tableName: 'coupons' })
@Unique({ properties: ['code', 'restaurant'] }) @Unique({ properties: ['code', 'restaurant'] })
+4
View File
@@ -0,0 +1,4 @@
export enum CouponType {
PERCENTAGE = 'PERCENTAGE',
FIXED = 'FIXED',
}
@@ -6,7 +6,8 @@ import { CouponRepository } from '../repositories/coupon.repository';
import { RestRepository } from '../../restaurants/repositories/rest.repository'; import { RestRepository } from '../../restaurants/repositories/rest.repository';
import { EntityManager } from '@mikro-orm/postgresql'; import { EntityManager } from '@mikro-orm/postgresql';
import { RequiredEntityData } from '@mikro-orm/core'; import { RequiredEntityData } from '@mikro-orm/core';
import { Coupon, CouponType } from '../entities/coupon.entity'; import { Coupon } from '../entities/coupon.entity';
import { CouponType } from '../interface/coupon';
import { CouponMessage, RestMessage } from 'src/common/enums/message.enum'; import { CouponMessage, RestMessage } from 'src/common/enums/message.enum';
import { randomBytes } from 'node:crypto'; import { randomBytes } from 'node:crypto';
@@ -1,7 +1,8 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql'; import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
import { FilterQuery } from '@mikro-orm/core'; import { FilterQuery } from '@mikro-orm/core';
import { Coupon, CouponType } from '../entities/coupon.entity'; import { Coupon } from '../entities/coupon.entity';
import { CouponType } from '../interface/coupon';
import { PaginatedResult } from 'src/common/interfaces/pagination.interface'; import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
type FindCouponsOpts = { type FindCouponsOpts = {
+1 -1
View File
@@ -1,4 +1,4 @@
import type { CouponType } from 'src/modules/coupons/entities/coupon.entity'; import type { CouponType } from 'src/modules/coupons/interface/coupon';
export enum OrderStatus { export enum OrderStatus {
Pending = 'pending', Pending = 'pending',
+1 -1
View File
@@ -1,4 +1,4 @@
import { CouponType } from '../../modules/coupons/entities/coupon.entity'; import { CouponType } from '../../modules/coupons/interface/coupon';
export interface CouponData { export interface CouponData {
restaurantSlug: string; restaurantSlug: string;