import { EntityManager } from "@mikro-orm/postgresql"; import { Seeder } from "@mikro-orm/seeder"; import { Logger } from "@nestjs/common"; import { genSalt, hash } from "bcrypt"; import { Business } from "../../src/modules/businesses/entities/business.entity"; import { CompanyProduct } from "../../src/modules/companies/entities/company-product.entity"; import { CompanyService } from "../../src/modules/companies/entities/company-service.entity"; import { Company } from "../../src/modules/companies/entities/company.entity"; import { CompanyStatus } from "../../src/modules/companies/enums/company-status.enum"; import { Industry } from "../../src/modules/industries/entities/industry.entity"; import { Role } from "../../src/modules/users/entities/role.entity"; import { User } from "../../src/modules/users/entities/user.entity"; import { RoleEnum } from "../../src/modules/users/enums/role.enum"; /** Business ID to seed test companies for. Change or use env if needed. */ const TEST_BUSINESS_ID = "e5e760b9-46a5-4194-bb3d-00a46c24d72a"; /** All test companies/users use this prefix so they can be safely deleted later. */ export const TEST_SEED_PREFIX = "TEST_SEED_"; const TEST_COMPANIES_COUNT = 1000; const BATCH_SIZE = 50; const TEST_PASSWORD = "TestPassword1!"; export class TestCompaniesSeeder extends Seeder { private readonly logger = new Logger(TestCompaniesSeeder.name); async run(em: EntityManager): Promise { const business = await em.findOne(Business, { id: TEST_BUSINESS_ID, deletedAt: null }); if (!business) { this.logger.error(`Business not found: ${TEST_BUSINESS_ID}. Aborting.`); throw new Error(`Business not found: ${TEST_BUSINESS_ID}`); } const industry = await em.findOne(Industry, { business: { id: TEST_BUSINESS_ID }, deletedAt: null }); if (!industry) { this.logger.error(`No industry found for business ${TEST_BUSINESS_ID}. Create an industry first.`); throw new Error("No industry found for business"); } const role = await em.findOne(Role, { name: RoleEnum.USER }); if (!role) { this.logger.error("USER role not found. Run default seed first (RoleSeeder)."); throw new Error("USER role not found"); } const hashedPassword = await hash(TEST_PASSWORD, await genSalt(10)); const baseDate = "2020-01-01"; const baseUrl = "https://example.com"; this.logger.log(`Seeding ${TEST_COMPANIES_COUNT} test companies for business ${TEST_BUSINESS_ID}...`); for (let i = 1; i <= TEST_COMPANIES_COUNT; i++) { const pad4 = String(i).padStart(4, "0"); const pad5 = String(i).padStart(5, "0"); const pad7 = String(i).padStart(7, "0"); const phone = `0912${pad7}`; const email = `test.seed.${i}@test.local`; const nationalCode = `0000${pad5}`; const userName = `testseed${i}`; const user = em.create(User, { firstName: "Test", lastName: `User${i}`, email, phone, userName, nationalCode, password: hashedPassword, role, business, }); await em.persist(user); const company = em.create(Company, { name: `${TEST_SEED_PREFIX}Company_${pad4}`, chiefExecutiveOfficer: `Test CEO ${i}`, email, phone, identificationNumber: `TESTSEEDID${pad5}`, dateOfEstablishment: new Date(baseDate), address: `${TEST_SEED_PREFIX} Address ${i}`, mapAddressLink: `${baseUrl}/map`, description: `${TEST_SEED_PREFIX} Description ${i}`, websiteUrl: `${baseUrl}`, profileImageUrl: `${baseUrl}/profile.png`, coverImageUrl: `${baseUrl}/cover.png`, metrage: 100, isActive: true, status: CompanyStatus.APPROVED, industry, business, user, }); const product = em.create(CompanyProduct, { title: `${TEST_SEED_PREFIX}Product_${i}`, imageUrl: `${baseUrl}/product.png`, company, }); const service = em.create(CompanyService, { title: `${TEST_SEED_PREFIX}Service_${i}`, imageUrl: `${baseUrl}/service.png`, company, }); company.products.add(product); company.services.add(service); await em.persist(company); if (i % BATCH_SIZE === 0) { await em.flush(); this.logger.log(` ... ${i}/${TEST_COMPANIES_COUNT}`); } } await em.flush(); this.logger.log(`Done. Created ${TEST_COMPANIES_COUNT} test companies (name like '${TEST_SEED_PREFIX}%').`); this.logger.warn(`To remove them later, run: pnpm run seed:cleanup-test-companies`); } }