diff --git a/src/modules/restaurants/dto/create-restaurant.dto.ts b/src/modules/restaurants/dto/create-restaurant.dto.ts index 350c305..7d41d62 100644 --- a/src/modules/restaurants/dto/create-restaurant.dto.ts +++ b/src/modules/restaurants/dto/create-restaurant.dto.ts @@ -35,10 +35,13 @@ export class CreateRestaurantDto { @IsNumber() longitude?: number; - @ApiPropertyOptional({ example: 5000, description: 'حوزه سرویس‌دهی به متر' }) + @ApiPropertyOptional({ + example: 'POLYGON((51.389 35.6892, 51.390 35.6892, 51.390 35.6902, 51.389 35.6902, 51.389 35.6892))', + description: 'محدوده سرویس‌دهی به صورت PostGIS Polygon (WKT format)', + }) @IsOptional() - @IsNumber() - serviceArea?: number; + @IsString() + serviceArea?: string; @ApiPropertyOptional({ example: 2020, description: 'سال تأسیس' }) @IsOptional() diff --git a/src/modules/restaurants/dto/restaurant-specification.dto.ts b/src/modules/restaurants/dto/restaurant-specification.dto.ts index 2a1345b..6fd8133 100644 --- a/src/modules/restaurants/dto/restaurant-specification.dto.ts +++ b/src/modules/restaurants/dto/restaurant-specification.dto.ts @@ -25,8 +25,11 @@ export class RestaurantSpecificationDto { @ApiPropertyOptional({ example: 51.389, description: 'Longitude' }) longitude?: number; - @ApiPropertyOptional({ example: 5000, description: 'Service area in meters' }) - serviceArea?: number; + @ApiPropertyOptional({ + example: 'POLYGON((51.389 35.6892, 51.390 35.6892, 51.390 35.6902, 51.389 35.6902, 51.389 35.6892))', + description: 'Service area as PostGIS Polygon (WKT format)', + }) + serviceArea?: string; @ApiPropertyOptional({ example: 2020, description: 'Established year' }) establishedYear?: number; diff --git a/src/modules/restaurants/entities/restaurant.entity.ts b/src/modules/restaurants/entities/restaurant.entity.ts index ecba2fa..4700d5e 100644 --- a/src/modules/restaurants/entities/restaurant.entity.ts +++ b/src/modules/restaurants/entities/restaurant.entity.ts @@ -1,5 +1,6 @@ import { Entity, Property } from '@mikro-orm/core'; import { BaseEntity } from '../../../common/entities/base.entity'; +import { PolygonType } from '../types/polygun.type'; @Entity({ tableName: 'restaurants' }) export class Restaurant extends BaseEntity { @@ -20,15 +21,14 @@ export class Restaurant extends BaseEntity { menuColor?: string; // --- مختصات جغرافیایی --- - @Property({ nullable: true }) + @Property({ type: 'decimal', precision: 10, scale: 7, nullable: true }) latitude?: number; - @Property({ nullable: true }) + @Property({ type: 'decimal', precision: 10, scale: 7, nullable: true }) longitude?: number; - // --- شعاع خدمات (مثلاً بر حسب متر یا کیلومتر) --- - @Property({ nullable: true }) - serviceArea?: number; + @Property({ type: PolygonType, nullable: true }) + serviceArea?: string; // --- وضعیت‌ها --- @Property({ default: true }) diff --git a/src/modules/restaurants/types/polygun.type.ts b/src/modules/restaurants/types/polygun.type.ts new file mode 100644 index 0000000..955c3c8 --- /dev/null +++ b/src/modules/restaurants/types/polygun.type.ts @@ -0,0 +1,42 @@ +import { Type } from '@mikro-orm/core'; +import type { Platform, TransformContext } from '@mikro-orm/core'; + +export class PolygonType extends Type { + getColumnType() { + return 'geometry(Polygon, 4326)'; + } + + convertToDatabaseValue( + value: string | null | undefined, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _platform: Platform, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _context?: TransformContext, + ): string | null { + if (value === null || value === undefined) { + return null; + } + // Convert WKT string to PostGIS geometry + // The value should be in WKT format: "POLYGON((lon1 lat1, lon2 lat2, ...))" + // PostgreSQL will handle the conversion using ST_GeomFromText when inserting + return value; + } + + convertToJSValue( + value: string | null | undefined, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _platform: Platform, + ): string | null { + if (value === null || value === undefined) { + return null; + } + // PostgreSQL returns geometry as hex-encoded EWKB or we need to use ST_AsText + // For now, assuming the value is already in WKT format or will be converted via SQL + // If needed, you can use raw SQL in queries: SELECT ST_AsText(service_area) as service_area + return value; + } + + toJSON(value: string | null | undefined, platform: Platform): string | null { + return this.convertToJSValue(value, platform); + } +} diff --git a/src/seeders/DatabaseSeeder.ts b/src/seeders/DatabaseSeeder.ts index f9246ce..3718295 100644 --- a/src/seeders/DatabaseSeeder.ts +++ b/src/seeders/DatabaseSeeder.ts @@ -113,6 +113,7 @@ export class DatabaseSeeder extends Seeder { slug: 'zhivan', isActive: true, phone: '09123456789', + serviceArea: 'POLYGON((51.389 35.6892, 51.390 35.6892, 51.390 35.6902, 51.389 35.6902, 51.389 35.6892))', }); em.persist(restaurant); } @@ -124,6 +125,7 @@ export class DatabaseSeeder extends Seeder { slug: 'boote', isActive: true, phone: '09123456790', + serviceArea: 'POLYGON((51.389 35.6892, 51.390 35.6892, 51.390 35.6902, 51.389 35.6902, 51.389 35.6892))', }); em.persist(restaurant); }