Property system: - Rename belonging → property throughout (model, controller, routes, service) - Add property sub-models: buildingModel, landModel, belongingModel - Add property lifecycle events: createProperty, deleteProperty - Add propertyStatus component (model, controller, routes, service, seeder) - Add commodity and commodityTransaction model stubs Infrastructure: - Update transactionModel and transactionService - Update events/index.js for new property events - Update seeder (seederDBConnection, seederRunner) - Update typesense client configuration - Update upload utilities (bucket, minio) - Update featureModel and featureSeeder - Update categorySeeder - Update TsApiFeatures utility - Remove docker-compose.yml (moved to root) - Remove legacy belonging component files
686 lines
23 KiB
JavaScript
686 lines
23 KiB
JavaScript
const Feature = require('./featureModel')
|
|
const Category = require('../category/categoryModel')
|
|
const chalk = require('chalk')
|
|
|
|
const runSeeder = async () => {
|
|
// Fetch all categories dynamically so we don't rely on hardcoded ObjectIDs
|
|
const allCategories = await Category.find({})
|
|
const categoryMap = {}
|
|
for (const cat of allCategories) {
|
|
categoryMap[cat.englishName] = cat._id
|
|
}
|
|
|
|
const lot = categoryMap['Lot']
|
|
const building = categoryMap['Building']
|
|
const car = categoryMap['Car']
|
|
|
|
if (!lot || !building || !car) {
|
|
console.log(chalk.red('One or more required categories not found. Run category seeder first.'))
|
|
console.log('Found categories:', Object.keys(categoryMap))
|
|
return
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
// Helper: builds the shared registration/ownership/legal block for a given
|
|
// category ObjectID. Used for both Lot and Building.
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
const sharedRealEstateFields = (category) => [
|
|
{
|
|
nativeName: 'نام مالک',
|
|
englishName: 'ownerName',
|
|
category,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'مالکیت',
|
|
priority: 200,
|
|
},
|
|
{
|
|
nativeName: 'پلاک ثبتی',
|
|
englishName: 'registrationPlate',
|
|
category,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'ثبت',
|
|
priority: 195,
|
|
},
|
|
{
|
|
nativeName: 'شماره اصلی',
|
|
englishName: 'mainNumber',
|
|
category,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'ثبت',
|
|
priority: 194,
|
|
},
|
|
{
|
|
nativeName: 'شماره فرعی',
|
|
englishName: 'subNumber',
|
|
category,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'ثبت',
|
|
priority: 193,
|
|
},
|
|
{
|
|
nativeName: 'بخش ثبتی',
|
|
englishName: 'registrationSection',
|
|
category,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: true,
|
|
tag: 'ثبت',
|
|
priority: 192,
|
|
},
|
|
{
|
|
nativeName: 'قطعه',
|
|
englishName: 'plotNumber',
|
|
category,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'ثبت',
|
|
priority: 191,
|
|
},
|
|
{
|
|
nativeName: 'ناحیه',
|
|
englishName: 'district',
|
|
category,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: true,
|
|
tag: 'موقعیت',
|
|
priority: 190,
|
|
},
|
|
{
|
|
nativeName: 'کدپستی',
|
|
englishName: 'postalCode',
|
|
category,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'موقعیت',
|
|
priority: 189,
|
|
},
|
|
{
|
|
nativeName: 'شناسه ملی جغرافیایی',
|
|
englishName: 'nationalGeoId',
|
|
category,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'ثبت',
|
|
priority: 188,
|
|
},
|
|
{
|
|
nativeName: 'آدرس',
|
|
englishName: 'address',
|
|
category,
|
|
featureType: 'textarea',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'موقعیت',
|
|
priority: 187,
|
|
},
|
|
{
|
|
nativeName: 'حدود مفروزات',
|
|
englishName: 'propertyBoundaries',
|
|
category,
|
|
featureType: 'textarea',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'ثبت',
|
|
priority: 186,
|
|
},
|
|
{
|
|
nativeName: 'مستندات مالکیت',
|
|
englishName: 'ownershipDocs',
|
|
category,
|
|
featureType: 'textarea',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'مالکیت',
|
|
priority: 185,
|
|
},
|
|
{
|
|
nativeName: 'وضعیت خاص',
|
|
englishName: 'specialStatus',
|
|
category,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['توقیف', 'رهن', 'وراثتی', 'اوقافی', 'دولتی', 'در دست ساخت', 'مسدود'],
|
|
isFilterable: true,
|
|
tag: 'مالکیت',
|
|
priority: 184,
|
|
},
|
|
{
|
|
nativeName: 'نوع سند',
|
|
englishName: 'documentType',
|
|
category,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['سند تکبرگ', 'منگولهدار', 'وقفی', 'مشاع', 'بنچاق', 'قولنامهای'],
|
|
isFilterable: true,
|
|
tag: 'سند',
|
|
priority: 183,
|
|
},
|
|
]
|
|
|
|
const features = [
|
|
// ──────────────────────────────────────────────────────────────────────
|
|
// زمین (Lot) features
|
|
// ──────────────────────────────────────────────────────────────────────
|
|
...sharedRealEstateFields(lot),
|
|
|
|
{
|
|
nativeName: 'متراژ',
|
|
englishName: 'area',
|
|
category: lot,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
unit: 'متر مربع',
|
|
isFilterable: true,
|
|
tag: 'ابعاد',
|
|
priority: 100,
|
|
},
|
|
{
|
|
nativeName: 'کاربری زمین',
|
|
englishName: 'landUsage',
|
|
category: lot,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['مسکونی', 'تجاری', 'کشاورزی', 'صنعتی', 'ویلایی', 'باغی', 'آموزشی', 'اداری'],
|
|
isFilterable: true,
|
|
tag: 'کاربری',
|
|
priority: 95,
|
|
},
|
|
{
|
|
nativeName: 'نوع ملک',
|
|
englishName: 'propertyType',
|
|
category: lot,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['زمین مسکونی', 'زمین تجاری', 'زمین کشاورزی', 'زمین صنعتی', 'باغ', 'مزرعه'],
|
|
isFilterable: true,
|
|
tag: 'مشخصات',
|
|
priority: 90,
|
|
},
|
|
{
|
|
nativeName: 'موقعیت جغرافیایی',
|
|
englishName: 'geoPosition',
|
|
category: lot,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['شمالی', 'جنوبی', 'شرقی', 'غربی', 'کنج'],
|
|
isFilterable: true,
|
|
tag: 'موقعیت',
|
|
priority: 80,
|
|
},
|
|
{
|
|
nativeName: 'عرض گذر',
|
|
englishName: 'streetWidth',
|
|
category: lot,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
unit: 'متر',
|
|
isFilterable: true,
|
|
tag: 'ابعاد',
|
|
priority: 75,
|
|
},
|
|
{
|
|
nativeName: 'تعداد بر',
|
|
englishName: 'facadeCount',
|
|
category: lot,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
isFilterable: true,
|
|
tag: 'ابعاد',
|
|
priority: 70,
|
|
},
|
|
{
|
|
nativeName: 'طول زمین',
|
|
englishName: 'landLength',
|
|
category: lot,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
unit: 'متر',
|
|
isFilterable: false,
|
|
tag: 'ابعاد',
|
|
priority: 65,
|
|
},
|
|
{
|
|
nativeName: 'عرض زمین',
|
|
englishName: 'landWidth',
|
|
category: lot,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
unit: 'متر',
|
|
isFilterable: false,
|
|
tag: 'ابعاد',
|
|
priority: 64,
|
|
},
|
|
{
|
|
nativeName: 'جهت ساختمان',
|
|
englishName: 'buildingDirection',
|
|
category: lot,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['شمالی', 'جنوبی', 'شرقی', 'غربی'],
|
|
isFilterable: true,
|
|
tag: 'موقعیت',
|
|
priority: 60,
|
|
},
|
|
{
|
|
nativeName: 'امکانات زیرساختی',
|
|
englishName: 'utilities',
|
|
category: lot,
|
|
featureType: 'string',
|
|
filterType: 'multi',
|
|
predefinedValues: ['آب', 'برق', 'گاز', 'فاضلاب', 'تلفن', 'اینترنت'],
|
|
isFilterable: true,
|
|
tag: 'امکانات',
|
|
priority: 55,
|
|
},
|
|
{
|
|
nativeName: 'قیمت هر متر مربع',
|
|
englishName: 'pricePerMeter',
|
|
category: lot,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
unit: 'تومان',
|
|
isFilterable: true,
|
|
tag: 'قیمت',
|
|
priority: 50,
|
|
},
|
|
{
|
|
nativeName: 'منطقه شهرداری',
|
|
englishName: 'municipalityZone',
|
|
category: lot,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: true,
|
|
tag: 'موقعیت',
|
|
priority: 45,
|
|
},
|
|
|
|
// ──────────────────────────────────────────────────────────────────────
|
|
// ساختمان (Building) features
|
|
// ──────────────────────────────────────────────────────────────────────
|
|
...sharedRealEstateFields(building),
|
|
|
|
{
|
|
nativeName: 'متراژ',
|
|
englishName: 'area',
|
|
category: building,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
unit: 'متر مربع',
|
|
isFilterable: true,
|
|
tag: 'ابعاد',
|
|
priority: 100,
|
|
},
|
|
{
|
|
nativeName: 'نوع ملک',
|
|
englishName: 'propertyType',
|
|
category: building,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['آپارتمان', 'ویلا', 'خانه مستقل', 'دوبلکس', 'پنتهاوس', 'مغازه', 'دفتر', 'سوله'],
|
|
isFilterable: true,
|
|
tag: 'مشخصات',
|
|
priority: 99,
|
|
},
|
|
{
|
|
nativeName: 'تعداد اتاق',
|
|
englishName: 'roomCount',
|
|
category: building,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
isFilterable: true,
|
|
tag: 'مشخصات',
|
|
priority: 95,
|
|
},
|
|
{
|
|
nativeName: 'طبقه',
|
|
englishName: 'floor',
|
|
category: building,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
isFilterable: true,
|
|
tag: 'مشخصات',
|
|
priority: 90,
|
|
},
|
|
{
|
|
nativeName: 'تعداد طبقات کل',
|
|
englishName: 'totalFloors',
|
|
category: building,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
isFilterable: true,
|
|
tag: 'مشخصات',
|
|
priority: 85,
|
|
},
|
|
{
|
|
nativeName: 'سال ساخت',
|
|
englishName: 'buildYear',
|
|
category: building,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
isFilterable: true,
|
|
tag: 'عمومی',
|
|
priority: 80,
|
|
},
|
|
{
|
|
nativeName: 'پارکینگ',
|
|
englishName: 'parking',
|
|
category: building,
|
|
featureType: 'boolean',
|
|
filterType: 'bool',
|
|
isFilterable: true,
|
|
tag: 'امکانات',
|
|
priority: 75,
|
|
},
|
|
{
|
|
nativeName: 'انباری',
|
|
englishName: 'storage',
|
|
category: building,
|
|
featureType: 'boolean',
|
|
filterType: 'bool',
|
|
isFilterable: true,
|
|
tag: 'امکانات',
|
|
priority: 74,
|
|
},
|
|
{
|
|
nativeName: 'آسانسور',
|
|
englishName: 'elevator',
|
|
category: building,
|
|
featureType: 'boolean',
|
|
filterType: 'bool',
|
|
isFilterable: true,
|
|
tag: 'امکانات',
|
|
priority: 73,
|
|
},
|
|
{
|
|
nativeName: 'بالکن',
|
|
englishName: 'balcony',
|
|
category: building,
|
|
featureType: 'boolean',
|
|
filterType: 'bool',
|
|
isFilterable: true,
|
|
tag: 'امکانات',
|
|
priority: 72,
|
|
},
|
|
{
|
|
nativeName: 'وضعیت بنا',
|
|
englishName: 'houseCondition',
|
|
category: building,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['نوساز', 'بازسازی شده', 'کلنگی', 'قدیمی'],
|
|
isFilterable: true,
|
|
tag: 'مشخصات',
|
|
priority: 70,
|
|
},
|
|
{
|
|
nativeName: 'سیستم گرمایش',
|
|
englishName: 'heatingSystem',
|
|
category: building,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['شوفاژ', 'پکیج', 'فنکوئل', 'گرمای کفی', 'بخاری'],
|
|
isFilterable: true,
|
|
tag: 'امکانات',
|
|
priority: 65,
|
|
},
|
|
{
|
|
nativeName: 'سیستم سرمایش',
|
|
englishName: 'coolingSystem',
|
|
category: building,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['کولر آبی', 'اسپیلت', 'فنکوئل', 'چیلر'],
|
|
isFilterable: true,
|
|
tag: 'امکانات',
|
|
priority: 64,
|
|
},
|
|
{
|
|
nativeName: 'متریال کف',
|
|
englishName: 'floorMaterial',
|
|
category: building,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['سرامیک', 'پارکت', 'موزاییک', 'سنگ', 'اپوکسی'],
|
|
isFilterable: false,
|
|
tag: 'مشخصات',
|
|
priority: 60,
|
|
},
|
|
{
|
|
nativeName: 'موقعیت جغرافیایی',
|
|
englishName: 'geoPosition',
|
|
category: building,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['شمالی', 'جنوبی', 'شرقی', 'غربی', 'کنج'],
|
|
isFilterable: true,
|
|
tag: 'موقعیت',
|
|
priority: 55,
|
|
},
|
|
{
|
|
nativeName: 'منطقه شهرداری',
|
|
englishName: 'municipalityZone',
|
|
category: building,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: true,
|
|
tag: 'موقعیت',
|
|
priority: 50,
|
|
},
|
|
|
|
// ──────────────────────────────────────────────────────────────────────
|
|
// خودرو (Car) features
|
|
// ──────────────────────────────────────────────────────────────────────
|
|
{
|
|
nativeName: 'شماره VIN',
|
|
englishName: 'vinNumber',
|
|
category: car,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'شناسه',
|
|
priority: 100,
|
|
},
|
|
{
|
|
nativeName: 'نوع پلاک',
|
|
englishName: 'plateType',
|
|
category: car,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: [
|
|
'پلاک ملی',
|
|
'پلاک منطقه آزاد اروند دائمی',
|
|
'پلاک منطقه آزاد اروند موقت',
|
|
'پلاک گذر موقت',
|
|
],
|
|
isFilterable: true,
|
|
tag: 'پلاک',
|
|
priority: 95,
|
|
},
|
|
{
|
|
nativeName: 'شماره پلاک',
|
|
englishName: 'plateNumber',
|
|
category: car,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: false,
|
|
tag: 'پلاک',
|
|
priority: 90,
|
|
},
|
|
{
|
|
nativeName: 'برند',
|
|
englishName: 'brand',
|
|
category: car,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: [
|
|
'ایرانخودرو',
|
|
'سایپا',
|
|
'بهمن',
|
|
'کیا',
|
|
'هیوندا',
|
|
'تویوتا',
|
|
'بنز',
|
|
'BMW',
|
|
'آئودی',
|
|
'پژو',
|
|
'رنو',
|
|
'فولکس واگن',
|
|
'شورولت',
|
|
'فورد',
|
|
'لکسوس',
|
|
],
|
|
isFilterable: true,
|
|
tag: 'مشخصات',
|
|
priority: 85,
|
|
},
|
|
{
|
|
nativeName: 'مدل خودرو',
|
|
englishName: 'model',
|
|
category: car,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
isFilterable: true,
|
|
tag: 'مشخصات',
|
|
priority: 80,
|
|
},
|
|
{
|
|
nativeName: 'سال تولید',
|
|
englishName: 'productionYear',
|
|
category: car,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
isFilterable: true,
|
|
tag: 'مشخصات',
|
|
priority: 75,
|
|
},
|
|
{
|
|
nativeName: 'رنگ',
|
|
englishName: 'color',
|
|
category: car,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['سفید', 'مشکی', 'نقرهای', 'خاکستری', 'قرمز', 'آبی', 'سبز', 'طلایی', 'کرم'],
|
|
isFilterable: true,
|
|
tag: 'مشخصات',
|
|
priority: 70,
|
|
},
|
|
{
|
|
nativeName: 'کارکرد (کیلومتر)',
|
|
englishName: 'mileage',
|
|
category: car,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
unit: 'کیلومتر',
|
|
isFilterable: true,
|
|
tag: 'وضعیت',
|
|
priority: 65,
|
|
},
|
|
{
|
|
nativeName: 'نوع سوخت',
|
|
englishName: 'fuelType',
|
|
category: car,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['بنزین', 'گازوئیل', 'برقی', 'هیبریدی', 'CNG', 'دوگانهسوز'],
|
|
isFilterable: true,
|
|
tag: 'موتور',
|
|
priority: 60,
|
|
},
|
|
{
|
|
nativeName: 'نوع گیربکس',
|
|
englishName: 'transmission',
|
|
category: car,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['دستی', 'اتوماتیک', 'نیمهاتوماتیک', 'CVT'],
|
|
isFilterable: true,
|
|
tag: 'موتور',
|
|
priority: 55,
|
|
},
|
|
{
|
|
nativeName: 'ظرفیت موتور',
|
|
englishName: 'engineCapacity',
|
|
category: car,
|
|
featureType: 'number',
|
|
filterType: 'range',
|
|
unit: 'سیسی',
|
|
isFilterable: true,
|
|
tag: 'موتور',
|
|
priority: 50,
|
|
},
|
|
{
|
|
nativeName: 'تعداد سیلندر',
|
|
englishName: 'cylinderCount',
|
|
category: car,
|
|
featureType: 'number',
|
|
filterType: 'exact',
|
|
predefinedValues: ['3', '4', '6', '8'],
|
|
isFilterable: true,
|
|
tag: 'موتور',
|
|
priority: 45,
|
|
},
|
|
{
|
|
nativeName: 'وضعیت بدنه',
|
|
englishName: 'bodyCondition',
|
|
category: car,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['صفر', 'بدون خش', 'خط و خش جزئی', 'رنگ شده', 'تصادفی'],
|
|
isFilterable: true,
|
|
tag: 'وضعیت',
|
|
priority: 40,
|
|
},
|
|
{
|
|
nativeName: 'گواهی معاینه فنی',
|
|
englishName: 'technicalInspection',
|
|
category: car,
|
|
featureType: 'boolean',
|
|
filterType: 'bool',
|
|
isFilterable: true,
|
|
tag: 'وضعیت',
|
|
priority: 35,
|
|
},
|
|
{
|
|
nativeName: 'بیمه بدنه',
|
|
englishName: 'bodyInsurance',
|
|
category: car,
|
|
featureType: 'boolean',
|
|
filterType: 'bool',
|
|
isFilterable: true,
|
|
tag: 'وضعیت',
|
|
priority: 30,
|
|
},
|
|
{
|
|
nativeName: 'نوع بدنه',
|
|
englishName: 'bodyType',
|
|
category: car,
|
|
featureType: 'string',
|
|
filterType: 'exact',
|
|
predefinedValues: ['سدان', 'هاچبک', 'شاسیبلند', 'وانت', 'کوپه', 'مینیون', 'کراساوور'],
|
|
isFilterable: true,
|
|
tag: 'مشخصات',
|
|
priority: 25,
|
|
},
|
|
]
|
|
|
|
await Feature.deleteMany({})
|
|
console.log(chalk.red('Deleted all feature records.'))
|
|
|
|
await Feature.insertMany(features)
|
|
console.log(chalk.green.bold(`FEATURES: Created ${features.length} feature(s)`))
|
|
}
|
|
|
|
module.exports = { runSeeder }
|