This commit is contained in:
2026-01-06 09:22:57 +03:30
parent 6d216ba0d7
commit 6e2ef6f62c
2 changed files with 49 additions and 8 deletions
@@ -8,9 +8,10 @@ export class CreateRestaurantDto {
@IsString() @IsString()
name!: string; name!: string;
@ApiProperty({ example: 'zhivan', description: 'شناسه (slug) رستوران، لاتین و بدون فاصله' }) @ApiPropertyOptional({ example: 'zhivan', description: 'شناسه (slug) رستوران، لاتین و بدون فاصله (اختیاری - در صورت عدم ارسال، از نام رستوران تولید می‌شود)' })
@IsOptional()
@IsString() @IsString()
slug!: string; slug?: string;
@ApiPropertyOptional({ example: 2020, description: 'سال تأسیس' }) @ApiPropertyOptional({ example: 2020, description: 'سال تأسیس' })
@IsOptional() @IsOptional()
@@ -13,6 +13,7 @@ import { Admin } from '../../admin/entities/admin.entity';
import { AdminRole } from '../../admin/entities/adminRole.entity'; import { AdminRole } from '../../admin/entities/adminRole.entity';
import { Role } from '../../roles/entities/role.entity'; import { Role } from '../../roles/entities/role.entity';
import { normalizePhone } from 'src/modules/utils/phone.util'; import { normalizePhone } from 'src/modules/utils/phone.util';
import slugify from 'slugify';
import { NotificationPreference } from '../../notifications/entities/notification-preference.entity'; import { NotificationPreference } from '../../notifications/entities/notification-preference.entity';
import { notificationPreferencesData } from '../../../seeders/data/notification-preferences.data'; import { notificationPreferencesData } from '../../../seeders/data/notification-preferences.data';
import { Order } from '../../orders/entities/order.entity'; import { Order } from '../../orders/entities/order.entity';
@@ -31,11 +32,25 @@ export class RestaurantsService {
async setupRestuarant(dto: CreateRestaurantDto): Promise<Restaurant> { async setupRestuarant(dto: CreateRestaurantDto): Promise<Restaurant> {
return await this.em.transactional(async (em) => { return await this.em.transactional(async (em) => {
// Validate unique constraints // Generate or validate slug
const validateSlug = await em.findOne(Restaurant, { slug: dto.slug }) let slug = dto.slug;
if (validateSlug) { if (!slug) {
throw new BadRequestException("Duplicate slug: " + dto.slug) // Generate slug from restaurant name
slug = slugify(dto.name, {
lower: true,
strict: true,
locale: 'fa'
});
} }
// Ensure slug uniqueness
let finalSlug = slug;
let counter = 1;
while (await em.findOne(Restaurant, { slug: finalSlug })) {
finalSlug = `${slug}-${counter}`;
counter++;
}
const validateSubscriptionId = await em.findOne(Restaurant, { subscriptionId: dto.subscriptionId }) const validateSubscriptionId = await em.findOne(Restaurant, { subscriptionId: dto.subscriptionId })
if (validateSubscriptionId) { if (validateSubscriptionId) {
throw new BadRequestException("Duplicate subscriptionId: " + dto.subscriptionId) throw new BadRequestException("Duplicate subscriptionId: " + dto.subscriptionId)
@@ -44,12 +59,12 @@ export class RestaurantsService {
// Create restaurant // Create restaurant
const restaurant = em.create(Restaurant, { const restaurant = em.create(Restaurant, {
name: dto.name, name: dto.name,
slug: dto.slug, slug: finalSlug,
establishedYear: dto.establishedYear, establishedYear: dto.establishedYear,
phone: dto.phone, phone: dto.phone,
isActive: true, isActive: true,
plan: dto.plan, plan: dto.plan,
domain: `https://dmenu-plus-front.dev.danakcorp.com/${dto.slug}`, domain: `https://dmenu-plus-front.dev.danakcorp.com/${finalSlug}`,
subscriptionId: dto.subscriptionId, subscriptionId: dto.subscriptionId,
subscriptionEndDate: dto.subscriptionEndDate, subscriptionEndDate: dto.subscriptionEndDate,
subscriptionStartDate: dto.subscriptionStartDate, subscriptionStartDate: dto.subscriptionStartDate,
@@ -149,6 +164,31 @@ export class RestaurantsService {
throw new NotFoundException(RestMessage.NOT_FOUND); throw new NotFoundException(RestMessage.NOT_FOUND);
} }
// Handle slug generation/update
if (dto.slug !== undefined || dto.name !== undefined) {
let slug = dto.slug;
if (!slug && dto.name) {
// Generate slug from restaurant name if slug not provided but name is
slug = slugify(dto.name, {
lower: true,
strict: true,
locale: 'fa'
});
}
// Ensure slug uniqueness if slug is being updated
if (slug) {
let finalSlug = slug;
let counter = 1;
while (await this.em.findOne(Restaurant, { slug: finalSlug, id: { $ne: id } })) {
finalSlug = `${slug}-${counter}`;
counter++;
}
dto.slug = finalSlug;
}
}
this.restRepository.assign(restaurant, dto); this.restRepository.assign(restaurant, dto);
await this.em.persistAndFlush(restaurant); await this.em.persistAndFlush(restaurant);