up
This commit is contained in:
@@ -14,6 +14,7 @@ import { UploaderModule } from './modules/uploader/uploader.module';
|
|||||||
import { AdminModule } from './modules/admin/admin.module';
|
import { AdminModule } from './modules/admin/admin.module';
|
||||||
// import { CacheService } from './modules/utils/cache.service';
|
// import { CacheService } from './modules/utils/cache.service';
|
||||||
import { ThrottlerModule } from '@nestjs/throttler';
|
import { ThrottlerModule } from '@nestjs/throttler';
|
||||||
|
import { RestaurantsModule } from './modules/restaurants/restaurants.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -41,6 +42,7 @@ import { ThrottlerModule } from '@nestjs/throttler';
|
|||||||
limit: 5, // max requests per window
|
limit: 5, // max requests per window
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
|
RestaurantsModule,
|
||||||
],
|
],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
// providers: [CacheService],
|
// providers: [CacheService],
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { IsString, IsOptional, IsNumber, IsBoolean, IsArray, IsUrl } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateRestaurantDto {
|
||||||
|
@ApiProperty({ example: 'Cafe Morteza' })
|
||||||
|
@IsString()
|
||||||
|
name!: string;
|
||||||
|
|
||||||
|
@ApiProperty({ example: 'cafe-morteza' })
|
||||||
|
@IsString()
|
||||||
|
slug!: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'https://example.com/logo.png' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsUrl()
|
||||||
|
logo?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'Tehran, Valiasr St. No. 123' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
address?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: '#ff6600' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
menuColor?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 35.6892 })
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
latitude?: number;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 51.389 })
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
longitude?: number;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 5000, description: 'Service area in meters' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
serviceArea?: number;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 2020 })
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
establishedYear?: number;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: '+989123456789' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
phoneNumber?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'https://instagram.com/cafemorteza' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsUrl()
|
||||||
|
instagram?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'https://t.me/cafemorteza' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsUrl()
|
||||||
|
telegram?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'https://wa.me/989123456789' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsUrl()
|
||||||
|
whatsapp?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'Cozy place with best coffee in town.' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'Best Cafe in Tehran' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
seoTitle?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 'Cafe Morteza serves high-quality coffee.' })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
seoDescription?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: ['coffee', 'breakfast', 'cafe'] })
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
tagNames?: string[];
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: true })
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
isOpenNow?: boolean;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ example: 0.09 })
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
vat?: number;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { PartialType } from '@nestjs/swagger';
|
||||||
|
import { CreateRestaurantDto } from './create-restaurant.dto';
|
||||||
|
|
||||||
|
export class UpdateRestaurantDto extends PartialType(CreateRestaurantDto) {}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import { Entity, Property } from '@mikro-orm/core';
|
||||||
|
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||||
|
|
||||||
|
@Entity({ tableName: 'restaurants' })
|
||||||
|
export class Restaurant extends BaseEntity {
|
||||||
|
// --- اطلاعات پایه ---
|
||||||
|
@Property()
|
||||||
|
name!: string;
|
||||||
|
|
||||||
|
@Property({ unique: true })
|
||||||
|
slug!: string;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
logo?: string;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
address?: string;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
menuColor?: string;
|
||||||
|
|
||||||
|
// --- مختصات جغرافیایی ---
|
||||||
|
@Property({ nullable: true })
|
||||||
|
latitude?: number;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
longitude?: number;
|
||||||
|
|
||||||
|
// --- شعاع خدمات (مثلاً بر حسب متر یا کیلومتر) ---
|
||||||
|
@Property({ nullable: true })
|
||||||
|
serviceArea?: number;
|
||||||
|
|
||||||
|
// --- وضعیتها ---
|
||||||
|
@Property({ default: true })
|
||||||
|
isActive: boolean = true;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
establishedYear?: number;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
phoneNumber?: string;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
instagram?: string;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
telegram?: string;
|
||||||
|
|
||||||
|
@Property({ nullable: true })
|
||||||
|
whatsapp?: string;
|
||||||
|
|
||||||
|
// --- توضیحات ---
|
||||||
|
@Property({ type: 'text', nullable: true })
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
// --- سئو ---
|
||||||
|
@Property({ nullable: true })
|
||||||
|
seoTitle?: string;
|
||||||
|
|
||||||
|
@Property({ nullable: true, type: 'text' })
|
||||||
|
seoDescription?: string;
|
||||||
|
|
||||||
|
@Property({ nullable: true, type: 'json' })
|
||||||
|
tagNames?: string[];
|
||||||
|
|
||||||
|
// --- مالیات یا VAT ---
|
||||||
|
@Property({ type: 'decimal', default: 0 })
|
||||||
|
vat?: number = 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
|
||||||
|
import { RestaurantsService } from './restaurants.service';
|
||||||
|
import { CreateRestaurantDto } from './dto/create-restaurant.dto';
|
||||||
|
import { UpdateRestaurantDto } from './dto/update-restaurant.dto';
|
||||||
|
|
||||||
|
@Controller('restaurants')
|
||||||
|
export class RestaurantsController {
|
||||||
|
constructor(private readonly restaurantsService: RestaurantsService) {}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
create(@Body() createRestaurantDto: CreateRestaurantDto) {
|
||||||
|
return this.restaurantsService.create(createRestaurantDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
findAll() {
|
||||||
|
return this.restaurantsService.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':slug')
|
||||||
|
findOne(@Param('slug') slug: string) {
|
||||||
|
return this.restaurantsService.findBySlug(slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Patch(':id')
|
||||||
|
update(@Param('id') id: string, @Body() updateRestaurantDto: UpdateRestaurantDto) {
|
||||||
|
return this.restaurantsService.update(+id, updateRestaurantDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(':id')
|
||||||
|
remove(@Param('id') id: string) {
|
||||||
|
return this.restaurantsService.remove(+id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { RestaurantsService } from './restaurants.service';
|
||||||
|
import { RestaurantsController } from './restaurants.controller';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
controllers: [RestaurantsController],
|
||||||
|
providers: [RestaurantsService],
|
||||||
|
})
|
||||||
|
export class RestaurantsModule {}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||||
|
import { CreateRestaurantDto } from './dto/create-restaurant.dto';
|
||||||
|
import { UpdateRestaurantDto } from './dto/update-restaurant.dto';
|
||||||
|
import { Restaurant } from './entities/restaurant.entity';
|
||||||
|
import { EntityManager } from '@mikro-orm/postgresql';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RestaurantsService {
|
||||||
|
constructor(private readonly em: EntityManager) {}
|
||||||
|
|
||||||
|
async create(dto: CreateRestaurantDto): Promise<Restaurant> {
|
||||||
|
const restaurant = this.em.create(Restaurant, {
|
||||||
|
...dto,
|
||||||
|
isActive: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.em.persistAndFlush(restaurant);
|
||||||
|
return restaurant;
|
||||||
|
}
|
||||||
|
|
||||||
|
findAll() {
|
||||||
|
return `This action returns all restaurants`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async findBySlug(slug: string): Promise<Restaurant> {
|
||||||
|
const restaurant = await this.em.findOne(Restaurant, { slug });
|
||||||
|
|
||||||
|
if (!restaurant) {
|
||||||
|
throw new NotFoundException(`Restaurant with slug "${slug}" not found`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return restaurant;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(id: number, updateRestaurantDto: UpdateRestaurantDto) {
|
||||||
|
return `This action updates a #${id} restaurant`;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(id: number) {
|
||||||
|
return `This action removes a #${id} restaurant`;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user