chore: add industry crud
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
import { EntityManager } from "@mikro-orm/postgresql";
|
||||||
|
import { Seeder } from "@mikro-orm/seeder";
|
||||||
|
import { Logger } from "@nestjs/common";
|
||||||
|
|
||||||
|
import { RoleSeeder } from "./role.seeder";
|
||||||
|
|
||||||
|
export class IndexSeeder extends Seeder {
|
||||||
|
private readonly logger = new Logger(IndexSeeder.name);
|
||||||
|
|
||||||
|
async run(em: EntityManager): Promise<void> {
|
||||||
|
this.logger.log("Starting seeding process...");
|
||||||
|
await new RoleSeeder().run(em);
|
||||||
|
this.logger.log("Seeding process completed successfully.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { EntityManager, RequiredEntityData } from "@mikro-orm/postgresql";
|
||||||
|
import { Seeder } from "@mikro-orm/seeder";
|
||||||
|
import { Logger } from "@nestjs/common";
|
||||||
|
|
||||||
|
import { Role } from "../../src/modules/users/entities/role.entity";
|
||||||
|
import { RoleEnum } from "../../src/modules/users/enums/role.enum";
|
||||||
|
|
||||||
|
export class RoleSeeder extends Seeder {
|
||||||
|
private readonly logger = new Logger(RoleSeeder.name);
|
||||||
|
|
||||||
|
async run(em: EntityManager): Promise<void> {
|
||||||
|
const roles: RequiredEntityData<Role>[] = [
|
||||||
|
{
|
||||||
|
name: RoleEnum.ADMIN,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: RoleEnum.USER,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const roleData of roles) {
|
||||||
|
const existingRole = await em.findOne(Role, { name: roleData.name });
|
||||||
|
if (!existingRole) {
|
||||||
|
const role = em.create(Role, roleData);
|
||||||
|
await em.persistAndFlush(role);
|
||||||
|
this.logger.log(`[RoleSeeder] Created role: ${roleData.name}`);
|
||||||
|
} else {
|
||||||
|
this.logger.log(`[RoleSeeder] Role already exists: ${roleData.name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-1
@@ -19,15 +19,25 @@
|
|||||||
"test:cov": "jest --coverage",
|
"test:cov": "jest --coverage",
|
||||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||||
"test:e2e": "jest --config ./test/jest-e2e.json",
|
"test:e2e": "jest --config ./test/jest-e2e.json",
|
||||||
"prepare": "husky"
|
"prepare": "husky || true",
|
||||||
|
"orm:create": "mikro-orm migration:create --config=database/mikro-orm.config.ts",
|
||||||
|
"orm:up": "mikro-orm migration:up --config=database/mikro-orm.config.ts",
|
||||||
|
"orm:down": "mikro-orm migration:down --config=database/mikro-orm.config.ts",
|
||||||
|
"orm:generate": "mikro-orm migration:create --blank --config=database/mikro-orm.config.ts",
|
||||||
|
"orm:update": "mikro-orm schema:update --run --config=database/mikro-orm.config.ts",
|
||||||
|
"orm:drop": "mikro-orm schema:drop --run --config=database/mikro-orm.config.ts",
|
||||||
|
"orm:seed": "mikro-orm seeder:create --config=database/mikro-orm.config.ts",
|
||||||
|
"seed:run": "mikro-orm seeder:run --config=database/mikro-orm.config.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.806.0",
|
"@aws-sdk/client-s3": "^3.806.0",
|
||||||
"@fastify/static": "^8.1.1",
|
"@fastify/static": "^8.1.1",
|
||||||
"@keyv/redis": "^4.4.0",
|
"@keyv/redis": "^4.4.0",
|
||||||
|
"@mikro-orm/cli": "^6.4.15",
|
||||||
"@mikro-orm/core": "^6.4.15",
|
"@mikro-orm/core": "^6.4.15",
|
||||||
"@mikro-orm/nestjs": "^6.1.1",
|
"@mikro-orm/nestjs": "^6.1.1",
|
||||||
"@mikro-orm/postgresql": "^6.4.15",
|
"@mikro-orm/postgresql": "^6.4.15",
|
||||||
|
"@mikro-orm/seeder": "^6.4.15",
|
||||||
"@nest-lab/fastify-multer": "^1.3.0",
|
"@nest-lab/fastify-multer": "^1.3.0",
|
||||||
"@nest-lab/throttler-storage-redis": "^1.1.0",
|
"@nest-lab/throttler-storage-redis": "^1.1.0",
|
||||||
"@nestjs-modules/mailer": "^2.0.2",
|
"@nestjs-modules/mailer": "^2.0.2",
|
||||||
|
|||||||
Generated
+65
@@ -17,6 +17,9 @@ importers:
|
|||||||
'@keyv/redis':
|
'@keyv/redis':
|
||||||
specifier: ^4.4.0
|
specifier: ^4.4.0
|
||||||
version: 4.4.0(keyv@5.3.3)
|
version: 4.4.0(keyv@5.3.3)
|
||||||
|
'@mikro-orm/cli':
|
||||||
|
specifier: ^6.4.15
|
||||||
|
version: 6.4.15(pg@8.15.6)
|
||||||
'@mikro-orm/core':
|
'@mikro-orm/core':
|
||||||
specifier: ^6.4.15
|
specifier: ^6.4.15
|
||||||
version: 6.4.15
|
version: 6.4.15
|
||||||
@@ -26,6 +29,9 @@ importers:
|
|||||||
'@mikro-orm/postgresql':
|
'@mikro-orm/postgresql':
|
||||||
specifier: ^6.4.15
|
specifier: ^6.4.15
|
||||||
version: 6.4.15(@mikro-orm/core@6.4.15)
|
version: 6.4.15(@mikro-orm/core@6.4.15)
|
||||||
|
'@mikro-orm/seeder':
|
||||||
|
specifier: ^6.4.15
|
||||||
|
version: 6.4.15(@mikro-orm/core@6.4.15)
|
||||||
'@nest-lab/fastify-multer':
|
'@nest-lab/fastify-multer':
|
||||||
specifier: ^1.3.0
|
specifier: ^1.3.0
|
||||||
version: 1.3.0(@nestjs/common@11.1.0(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-fastify@11.1.0(@fastify/static@8.1.1)(@nestjs/common@11.1.0(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.0))(rxjs@7.8.2)
|
version: 1.3.0(@nestjs/common@11.1.0(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-fastify@11.1.0(@fastify/static@8.1.1)(@nestjs/common@11.1.0(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.0))(rxjs@7.8.2)
|
||||||
@@ -972,6 +978,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
|
resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
'@jercle/yargonaut@1.1.5':
|
||||||
|
resolution: {integrity: sha512-zBp2myVvBHp1UaJsNTyS6q4UDKT7eRiqTS4oNTS6VQMd6mpxYOdbeK4pY279cDCdakGy6hG0J3ejoXZVsPwHqw==}
|
||||||
|
|
||||||
'@jest/console@29.7.0':
|
'@jest/console@29.7.0':
|
||||||
resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==}
|
resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==}
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||||
@@ -1086,6 +1095,11 @@ packages:
|
|||||||
'@microsoft/tsdoc@0.15.1':
|
'@microsoft/tsdoc@0.15.1':
|
||||||
resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==}
|
resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==}
|
||||||
|
|
||||||
|
'@mikro-orm/cli@6.4.15':
|
||||||
|
resolution: {integrity: sha512-w0AqJvclBoSihECEtxPD2JtuOzwkm2nBYQvnZexiTfO5BPgjP9xGbCEDEp8figQW1yWIVM93z9aqQ2M3cXsADg==}
|
||||||
|
engines: {node: '>= 18.12.0'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
'@mikro-orm/core@6.4.15':
|
'@mikro-orm/core@6.4.15':
|
||||||
resolution: {integrity: sha512-1uQ7lThYymUHf6k6soByJ0qmnYFZcfpczAdmGsfIkGwoE0Ix83RIea+UAJk4pSFeKgXYdiDZOAFu5t224P/lOw==}
|
resolution: {integrity: sha512-1uQ7lThYymUHf6k6soByJ0qmnYFZcfpczAdmGsfIkGwoE0Ix83RIea+UAJk4pSFeKgXYdiDZOAFu5t224P/lOw==}
|
||||||
engines: {node: '>= 18.12.0'}
|
engines: {node: '>= 18.12.0'}
|
||||||
@@ -1120,6 +1134,12 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@mikro-orm/core': ^6.0.0
|
'@mikro-orm/core': ^6.0.0
|
||||||
|
|
||||||
|
'@mikro-orm/seeder@6.4.15':
|
||||||
|
resolution: {integrity: sha512-jZ1Ai28mMkHSRYzxrGQEdYktRXqq5P54syNi1H3wkYmRjzYqwAD6hOKrBCOmOzYqskQRWLe042F07w/27Nqo7g==}
|
||||||
|
engines: {node: '>= 18.12.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@mikro-orm/core': ^6.0.0
|
||||||
|
|
||||||
'@modelcontextprotocol/sdk@1.11.1':
|
'@modelcontextprotocol/sdk@1.11.1':
|
||||||
resolution: {integrity: sha512-9LfmxKTb1v+vUS1/emSk1f5ePmTLkb9Le9AxOB5T0XM59EUumwcS45z05h7aiZx3GI0Bl7mjb3FMEglYj+acuQ==}
|
resolution: {integrity: sha512-9LfmxKTb1v+vUS1/emSk1f5ePmTLkb9Le9AxOB5T0XM59EUumwcS45z05h7aiZx3GI0Bl7mjb3FMEglYj+acuQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -3437,6 +3457,11 @@ packages:
|
|||||||
fflate@0.8.2:
|
fflate@0.8.2:
|
||||||
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
|
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
|
||||||
|
|
||||||
|
figlet@1.8.1:
|
||||||
|
resolution: {integrity: sha512-kEC3Sme+YvA8Hkibv0NR1oClGcWia0VB2fC1SlMy027cwe795Xx40Xiv/nw/iFAwQLupymWh+uhAAErn/7hwPg==}
|
||||||
|
engines: {node: '>= 0.4.0'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
file-entry-cache@8.0.0:
|
file-entry-cache@8.0.0:
|
||||||
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
|
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
|
||||||
engines: {node: '>=16.0.0'}
|
engines: {node: '>=16.0.0'}
|
||||||
@@ -5027,6 +5052,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
parent-require@1.0.0:
|
||||||
|
resolution: {integrity: sha512-2MXDNZC4aXdkkap+rBBMv0lUsfJqvX5/2FiYYnfCnorZt3Pk06/IOR5KeaoghgS2w07MLWgjbsnyaq6PdHn2LQ==}
|
||||||
|
engines: {node: '>= 0.4.0'}
|
||||||
|
|
||||||
parse-json@5.2.0:
|
parse-json@5.2.0:
|
||||||
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
|
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -7448,6 +7477,12 @@ snapshots:
|
|||||||
|
|
||||||
'@istanbuljs/schema@0.1.3': {}
|
'@istanbuljs/schema@0.1.3': {}
|
||||||
|
|
||||||
|
'@jercle/yargonaut@1.1.5':
|
||||||
|
dependencies:
|
||||||
|
chalk: 4.1.2
|
||||||
|
figlet: 1.8.1
|
||||||
|
parent-require: 1.0.0
|
||||||
|
|
||||||
'@jest/console@29.7.0':
|
'@jest/console@29.7.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
@@ -7668,6 +7703,26 @@ snapshots:
|
|||||||
|
|
||||||
'@microsoft/tsdoc@0.15.1': {}
|
'@microsoft/tsdoc@0.15.1': {}
|
||||||
|
|
||||||
|
'@mikro-orm/cli@6.4.15(pg@8.15.6)':
|
||||||
|
dependencies:
|
||||||
|
'@jercle/yargonaut': 1.1.5
|
||||||
|
'@mikro-orm/core': 6.4.15
|
||||||
|
'@mikro-orm/knex': 6.4.15(@mikro-orm/core@6.4.15)(pg@8.15.6)
|
||||||
|
fs-extra: 11.3.0
|
||||||
|
tsconfig-paths: 4.2.0
|
||||||
|
yargs: 17.7.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- better-sqlite3
|
||||||
|
- libsql
|
||||||
|
- mariadb
|
||||||
|
- mysql
|
||||||
|
- mysql2
|
||||||
|
- pg
|
||||||
|
- pg-native
|
||||||
|
- sqlite3
|
||||||
|
- supports-color
|
||||||
|
- tedious
|
||||||
|
|
||||||
'@mikro-orm/core@6.4.15':
|
'@mikro-orm/core@6.4.15':
|
||||||
dependencies:
|
dependencies:
|
||||||
dataloader: 2.2.3
|
dataloader: 2.2.3
|
||||||
@@ -7718,6 +7773,12 @@ snapshots:
|
|||||||
- supports-color
|
- supports-color
|
||||||
- tedious
|
- tedious
|
||||||
|
|
||||||
|
'@mikro-orm/seeder@6.4.15(@mikro-orm/core@6.4.15)':
|
||||||
|
dependencies:
|
||||||
|
'@mikro-orm/core': 6.4.15
|
||||||
|
fs-extra: 11.3.0
|
||||||
|
globby: 11.1.0
|
||||||
|
|
||||||
'@modelcontextprotocol/sdk@1.11.1':
|
'@modelcontextprotocol/sdk@1.11.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
content-type: 1.0.5
|
content-type: 1.0.5
|
||||||
@@ -10421,6 +10482,8 @@ snapshots:
|
|||||||
|
|
||||||
fflate@0.8.2: {}
|
fflate@0.8.2: {}
|
||||||
|
|
||||||
|
figlet@1.8.1: {}
|
||||||
|
|
||||||
file-entry-cache@8.0.0:
|
file-entry-cache@8.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
flat-cache: 4.0.1
|
flat-cache: 4.0.1
|
||||||
@@ -12506,6 +12569,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
callsites: 3.1.0
|
callsites: 3.1.0
|
||||||
|
|
||||||
|
parent-require@1.0.0: {}
|
||||||
|
|
||||||
parse-json@5.2.0:
|
parse-json@5.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.27.1
|
'@babel/code-frame': 7.27.1
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ import { databaseConfig } from "./configs/mikro-orm.config";
|
|||||||
import { rateLimitConfig } from "./configs/rateLimit.config";
|
import { rateLimitConfig } from "./configs/rateLimit.config";
|
||||||
import { HTTPLogger } from "./core/middlewares/logger.middleware";
|
import { HTTPLogger } from "./core/middlewares/logger.middleware";
|
||||||
import { AuthModule } from "./modules/auth/auth.module";
|
import { AuthModule } from "./modules/auth/auth.module";
|
||||||
|
import { CompaniesModule } from "./modules/companies/companies.module";
|
||||||
|
import { IndustriesModule } from "./modules/industries/industries.module";
|
||||||
import { NotificationModule } from "./modules/notifications/notifications.module";
|
import { NotificationModule } from "./modules/notifications/notifications.module";
|
||||||
|
import { UploaderModule } from "./modules/uploader/uploader.module";
|
||||||
import { UsersModule } from "./modules/users/users.module";
|
import { UsersModule } from "./modules/users/users.module";
|
||||||
import { UtilsModule } from "./modules/utils/utils.module";
|
import { UtilsModule } from "./modules/utils/utils.module";
|
||||||
@Module({
|
@Module({
|
||||||
@@ -40,6 +43,9 @@ import { UtilsModule } from "./modules/utils/utils.module";
|
|||||||
UsersModule,
|
UsersModule,
|
||||||
NotificationModule,
|
NotificationModule,
|
||||||
UtilsModule,
|
UtilsModule,
|
||||||
|
IndustriesModule,
|
||||||
|
CompaniesModule,
|
||||||
|
UploaderModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AppModule implements NestModule {
|
export class AppModule implements NestModule {
|
||||||
|
|||||||
@@ -523,3 +523,18 @@ export const enum AdminMessage {
|
|||||||
export const enum SmsMessage {
|
export const enum SmsMessage {
|
||||||
SEND_SMS_ERROR = "خطا در ارسال پیامک",
|
SEND_SMS_ERROR = "خطا در ارسال پیامک",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const enum IndustryMessage {
|
||||||
|
TITLE_REQUIRED = "عنوان صنعت مورد نیاز است",
|
||||||
|
TITLE_MUST_BE_A_STRING = "عنوان صنعت باید یک رشته باشد",
|
||||||
|
TITLE_LENGTH = "عنوان صنعت باید بین ۳ تا ۱۰۰ کاراکتر باشد",
|
||||||
|
ICON_URL_REQUIRED = "آیکون صنعت مورد نیاز است",
|
||||||
|
ICON_URL_MUST_BE_A_URL = "آیکون صنعت باید یک URL معتبر باشد",
|
||||||
|
IS_ACTIVE_REQUIRED = "وضعیت فعالیت صنعت مورد نیاز است",
|
||||||
|
IS_ACTIVE_MUST_BE_A_BOOLEAN = "وضعیت فعالیت صنعت باید یک بولین باشد",
|
||||||
|
INDUSTRY_CREATED_SUCCESSFULLY = "صنعت با موفقیت ایجاد شد",
|
||||||
|
INDUSTRY_ALREADY_EXISTS = "این صنعت قبلا ثبت شده است",
|
||||||
|
INDUSTRY_NOT_FOUND = "این صنعت یافت نشد",
|
||||||
|
UPDATED_SUCCESSFULLY = "صنعت با موفقیت به روز رسانی شد",
|
||||||
|
INDUSTRY_DELETED_SUCCESSFULLY = "صنعت با موفقیت حذف شد",
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ export class AuthService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
const otpCode = await this.otpService.generateAndSetInCache(phone, "REGISTER");
|
const otpCode = await this.otpService.generateAndSetInCache(phone, "REGISTER");
|
||||||
|
|
||||||
//
|
//
|
||||||
await this.notificationQueue.addOtpNotification(phone, { userPhone: phone, otp: otpCode });
|
await this.notificationQueue.addOtpNotification(phone, { userPhone: phone, otp: otpCode });
|
||||||
await this.smsService.sendSmsVerifyCode(phone, otpCode);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: AuthMessage.OTP_SENT,
|
message: AuthMessage.OTP_SENT,
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { Controller } from "@nestjs/common";
|
||||||
|
|
||||||
|
@Controller("companies")
|
||||||
|
export class CompaniesController {}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { MikroOrmModule } from "@mikro-orm/nestjs";
|
||||||
|
import { Module } from "@nestjs/common";
|
||||||
|
|
||||||
|
import { CompaniesController } from "./companies.controller";
|
||||||
|
import { Company } from "./entities/company.entity";
|
||||||
|
import { CompaniesService } from "./services/companies.service";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [MikroOrmModule.forFeature([Company])],
|
||||||
|
providers: [CompaniesService],
|
||||||
|
controllers: [CompaniesController],
|
||||||
|
exports: [CompaniesService],
|
||||||
|
})
|
||||||
|
export class CompaniesModule {}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { Entity, EntityRepositoryType, ManyToOne, Opt, Property } from "@mikro-orm/core";
|
||||||
|
|
||||||
|
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||||
|
import { Industry } from "../../industries/entities/industry.entity";
|
||||||
|
import { CompanyRepository } from "../repositories/company.repository";
|
||||||
|
|
||||||
|
@Entity({ repository: () => CompanyRepository })
|
||||||
|
export class Company extends BaseEntity {
|
||||||
|
@Property({ type: "varchar", length: 255, unique: true })
|
||||||
|
name!: string;
|
||||||
|
|
||||||
|
@Property({ type: "varchar", length: 255 })
|
||||||
|
chiefExecutive!: string;
|
||||||
|
|
||||||
|
@Property({ type: "varchar", length: 255, unique: true })
|
||||||
|
phone!: string;
|
||||||
|
|
||||||
|
@Property({ type: "varchar", length: 255, unique: true })
|
||||||
|
email!: string;
|
||||||
|
|
||||||
|
@Property({ type: "varchar", length: 255, unique: true })
|
||||||
|
identificationNumber!: string;
|
||||||
|
|
||||||
|
@Property({ type: "date" })
|
||||||
|
dateOfEstablishment!: Date;
|
||||||
|
|
||||||
|
@Property({ type: "varchar", length: 255 })
|
||||||
|
address!: string;
|
||||||
|
|
||||||
|
@Property({ type: "varchar", length: 255 })
|
||||||
|
mapAddressLink!: string;
|
||||||
|
|
||||||
|
@Property({ type: "text", nullable: false })
|
||||||
|
description!: string;
|
||||||
|
|
||||||
|
@Property({ type: "varchar", length: 255 })
|
||||||
|
websiteUrl!: string;
|
||||||
|
|
||||||
|
@Property({ type: "varchar", length: 255 })
|
||||||
|
profileImageUrl!: string;
|
||||||
|
|
||||||
|
@Property({ type: "varchar", length: 255 })
|
||||||
|
coverImageUrl!: string;
|
||||||
|
|
||||||
|
@Property({ type: "boolean", default: true })
|
||||||
|
isActive!: boolean & Opt;
|
||||||
|
|
||||||
|
@ManyToOne(() => Industry, { deleteRule: "restrict" })
|
||||||
|
industry!: Industry;
|
||||||
|
|
||||||
|
[EntityRepositoryType]?: CompanyRepository;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { EntityRepository } from "@mikro-orm/core";
|
||||||
|
|
||||||
|
import { Company } from "../entities/company.entity";
|
||||||
|
|
||||||
|
export class CompanyRepository extends EntityRepository<Company> {}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
|
||||||
|
import { CompanyRepository } from "../repositories/company.repository";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CompaniesService {
|
||||||
|
constructor(private readonly companyRepository: CompanyRepository) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
|
import { IsBoolean, IsNotEmpty, IsOptional, IsString, IsUrl, Length } from "class-validator";
|
||||||
|
|
||||||
|
import { IndustryMessage } from "../../../common/enums/message.enum";
|
||||||
|
|
||||||
|
export class CreateIndustryDto {
|
||||||
|
@IsNotEmpty({ message: IndustryMessage.TITLE_REQUIRED })
|
||||||
|
@IsString({ message: IndustryMessage.TITLE_MUST_BE_A_STRING })
|
||||||
|
@Length(3, 100, { message: IndustryMessage.TITLE_LENGTH })
|
||||||
|
@ApiProperty({ description: "The title of the industry", example: "Industry" })
|
||||||
|
title: string;
|
||||||
|
|
||||||
|
@IsNotEmpty({ message: IndustryMessage.ICON_URL_REQUIRED })
|
||||||
|
@IsUrl({ protocols: ["http", "https"] }, { message: IndustryMessage.ICON_URL_MUST_BE_A_URL })
|
||||||
|
@ApiProperty({ description: "The icon url of the industry", example: "https://example.com/icon.png" })
|
||||||
|
iconUrl: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsNotEmpty({ message: IndustryMessage.IS_ACTIVE_REQUIRED })
|
||||||
|
@IsBoolean({ message: IndustryMessage.IS_ACTIVE_MUST_BE_A_BOOLEAN })
|
||||||
|
@ApiProperty({ description: "The active status of the industry", example: true })
|
||||||
|
isActive?: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { ApiPropertyOptional } from "@nestjs/swagger";
|
||||||
|
import { Type } from "class-transformer";
|
||||||
|
import { IsIn, IsOptional, IsString } from "class-validator";
|
||||||
|
|
||||||
|
import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
||||||
|
import { CommonMessage } from "../../../common/enums/message.enum";
|
||||||
|
|
||||||
|
export class IndustryListQueryDto extends PaginationDto {
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsIn([1, 0], { message: CommonMessage.IS_ACTIVE_SHOULD_BE_1_0 })
|
||||||
|
@ApiPropertyOptional({ description: "ads status", example: 1 })
|
||||||
|
isActive?: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString({ message: CommonMessage.SEARCH_QUERY_STRING })
|
||||||
|
@ApiPropertyOptional({ description: "Search query", example: "search query" })
|
||||||
|
q?: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { PartialType } from "@nestjs/swagger";
|
||||||
|
|
||||||
|
import { CreateIndustryDto } from "./create-industry.dto";
|
||||||
|
|
||||||
|
export class UpdateIndustryDto extends PartialType(CreateIndustryDto) {}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { Collection, Entity, EntityRepositoryType, OneToMany, Opt, Property } from "@mikro-orm/core";
|
||||||
|
|
||||||
|
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||||
|
import { Company } from "../../companies/entities/company.entity";
|
||||||
|
import { IndustryRepository } from "../repositories/industry.repository";
|
||||||
|
|
||||||
|
@Entity({ repository: () => IndustryRepository })
|
||||||
|
export class Industry extends BaseEntity {
|
||||||
|
@Property({ type: "varchar", length: 255, unique: true })
|
||||||
|
title!: string;
|
||||||
|
|
||||||
|
@Property({ type: "varchar", length: 255 })
|
||||||
|
iconUrl!: string;
|
||||||
|
|
||||||
|
@Property({ type: "boolean", default: true })
|
||||||
|
isActive!: boolean & Opt;
|
||||||
|
|
||||||
|
@OneToMany(() => Company, (company) => company.industry)
|
||||||
|
companies = new Collection<Company>(this);
|
||||||
|
|
||||||
|
[EntityRepositoryType]?: IndustryRepository;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from "@nestjs/common";
|
||||||
|
|
||||||
|
import { CreateIndustryDto } from "./DTO/create-industry.dto";
|
||||||
|
import { IndustryListQueryDto } from "./DTO/industry-list-query.dto";
|
||||||
|
import { UpdateIndustryDto } from "./DTO/update-industry.dto";
|
||||||
|
import { IndustriesService } from "./services/industries.service";
|
||||||
|
import { ParamDto } from "../../common/DTO/param.dto";
|
||||||
|
|
||||||
|
@Controller("industries")
|
||||||
|
export class IndustriesController {
|
||||||
|
constructor(private readonly industriesService: IndustriesService) {}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
create(@Body() createIndustryDto: CreateIndustryDto) {
|
||||||
|
return this.industriesService.create(createIndustryDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(":id")
|
||||||
|
getIndustryById(@Param() paramDto: ParamDto) {
|
||||||
|
return this.industriesService.getIndustriesById(paramDto.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Patch(":id")
|
||||||
|
updateIndustry(@Param() paramDto: ParamDto, @Body() updateIndustryDto: UpdateIndustryDto) {
|
||||||
|
return this.industriesService.updateIndustry(paramDto.id, updateIndustryDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(":id")
|
||||||
|
deleteIndustry(@Param() paramDto: ParamDto) {
|
||||||
|
return this.industriesService.deleteIndustry(paramDto.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get("list")
|
||||||
|
getIndustriesForAdmin(@Query() query: IndustryListQueryDto) {
|
||||||
|
return this.industriesService.getIndustriesListForAdmin(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Patch(":id/toggle-status")
|
||||||
|
toggleStatus(@Param() paramDto: ParamDto) {
|
||||||
|
return this.industriesService.toggleStatus(paramDto.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { MikroOrmModule } from "@mikro-orm/nestjs";
|
||||||
|
import { Module } from "@nestjs/common";
|
||||||
|
|
||||||
|
import { Industry } from "./entities/industry.entity";
|
||||||
|
import { IndustriesController } from "./industries.controller";
|
||||||
|
import { IndustriesService } from "./services/industries.service";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [MikroOrmModule.forFeature([Industry])],
|
||||||
|
controllers: [IndustriesController],
|
||||||
|
providers: [IndustriesService],
|
||||||
|
exports: [IndustriesService],
|
||||||
|
})
|
||||||
|
export class IndustriesModule {}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { EntityRepository } from "@mikro-orm/postgresql";
|
||||||
|
|
||||||
|
import { PaginationUtils } from "../../utils/providers/pagination.utils";
|
||||||
|
import { IndustryListQueryDto } from "../DTO/industry-list-query.dto";
|
||||||
|
import { Industry } from "../entities/industry.entity";
|
||||||
|
|
||||||
|
export class IndustryRepository extends EntityRepository<Industry> {
|
||||||
|
//
|
||||||
|
async getIndustriesListForAdmin(queryDto: IndustryListQueryDto) {
|
||||||
|
const { limit, skip } = PaginationUtils(queryDto);
|
||||||
|
|
||||||
|
const queryBuilder = this.createQueryBuilder("i")
|
||||||
|
.leftJoinAndSelect("i.companies", "c")
|
||||||
|
.where({ deletedAt: null })
|
||||||
|
.orderBy({ createdAt: "DESC" })
|
||||||
|
.limit(limit)
|
||||||
|
.offset(skip);
|
||||||
|
|
||||||
|
if (queryDto.q) {
|
||||||
|
queryBuilder.andWhere({ name: { $ilike: `%${queryDto.q}%` } });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryDto.isActive !== undefined) {
|
||||||
|
queryBuilder.andWhere({ isActive: queryDto.isActive === 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
return queryBuilder.getResultAndCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import { EntityManager } from "@mikro-orm/postgresql";
|
||||||
|
import { BadRequestException, Injectable } from "@nestjs/common";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
import { IndustryMessage } from "../../../common/enums/message.enum";
|
||||||
|
import { CreateIndustryDto } from "../DTO/create-industry.dto";
|
||||||
|
import { IndustryListQueryDto } from "../DTO/industry-list-query.dto";
|
||||||
|
import { UpdateIndustryDto } from "../DTO/update-industry.dto";
|
||||||
|
import { IndustryRepository } from "../repositories/industry.repository";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class IndustriesService {
|
||||||
|
constructor(
|
||||||
|
private readonly industryRepository: IndustryRepository,
|
||||||
|
private readonly em: EntityManager,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
//-----------------------------------
|
||||||
|
|
||||||
|
async create(createIndustryDto: CreateIndustryDto) {
|
||||||
|
const existingIndustry = await this.industryRepository.findOne({ title: createIndustryDto.title });
|
||||||
|
if (existingIndustry) throw new BadRequestException(IndustryMessage.INDUSTRY_ALREADY_EXISTS);
|
||||||
|
|
||||||
|
const industry = this.industryRepository.create(createIndustryDto);
|
||||||
|
this.em.persistAndFlush(industry);
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: IndustryMessage.INDUSTRY_CREATED_SUCCESSFULLY,
|
||||||
|
industry,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//-----------------------------------
|
||||||
|
|
||||||
|
async getIndustriesById(id: string) {
|
||||||
|
const industry = await this.industryRepository.findOne({ id, deletedAt: null });
|
||||||
|
if (!industry) throw new BadRequestException(IndustryMessage.INDUSTRY_NOT_FOUND);
|
||||||
|
|
||||||
|
return { industry };
|
||||||
|
}
|
||||||
|
//-----------------------------------
|
||||||
|
|
||||||
|
async updateIndustry(id: string, updateIndustryDto: UpdateIndustryDto) {
|
||||||
|
const industry = await this.industryRepository.findOne({ id, deletedAt: null });
|
||||||
|
if (!industry) throw new BadRequestException(IndustryMessage.INDUSTRY_NOT_FOUND);
|
||||||
|
|
||||||
|
this.industryRepository.assign(industry, updateIndustryDto);
|
||||||
|
this.em.persistAndFlush(industry);
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: IndustryMessage.UPDATED_SUCCESSFULLY,
|
||||||
|
industry,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------
|
||||||
|
|
||||||
|
async deleteIndustry(id: string) {
|
||||||
|
const industry = await this.industryRepository.findOne({ id, deletedAt: null });
|
||||||
|
if (!industry) throw new BadRequestException(IndustryMessage.INDUSTRY_NOT_FOUND);
|
||||||
|
|
||||||
|
industry.deletedAt = dayjs().toDate();
|
||||||
|
|
||||||
|
this.em.flush();
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: IndustryMessage.INDUSTRY_DELETED_SUCCESSFULLY,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//-----------------------------------
|
||||||
|
|
||||||
|
async getIndustriesListForAdmin(queryDto: IndustryListQueryDto) {
|
||||||
|
const [industries, count] = await this.industryRepository.getIndustriesListForAdmin(queryDto);
|
||||||
|
return { industries, count, paginate: true };
|
||||||
|
}
|
||||||
|
//-----------------------------------
|
||||||
|
|
||||||
|
async toggleStatus(id: string) {
|
||||||
|
const industry = await this.industryRepository.findOne({ id, deletedAt: null });
|
||||||
|
if (!industry) throw new BadRequestException(IndustryMessage.INDUSTRY_NOT_FOUND);
|
||||||
|
|
||||||
|
industry.isActive = !industry.isActive;
|
||||||
|
this.em.flush();
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: IndustryMessage.UPDATED_SUCCESSFULLY,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
|
|
||||||
|
import { IFile } from "../../utils/interfaces/IFile";
|
||||||
|
|
||||||
|
export class UploadSingleFileDto {
|
||||||
|
@ApiProperty({ type: "string", format: "binary", nullable: false })
|
||||||
|
file: IFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UploadMultipleFileDto {
|
||||||
|
@ApiProperty({
|
||||||
|
required: true,
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "string",
|
||||||
|
format: "binary",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
files: IFile[];
|
||||||
|
}
|
||||||
Executable
+32
@@ -0,0 +1,32 @@
|
|||||||
|
import { FileInterceptor, FilesInterceptor } from "@nest-lab/fastify-multer";
|
||||||
|
import { Controller, Post, UploadedFile, UploadedFiles, UseInterceptors } from "@nestjs/common";
|
||||||
|
import { ApiBody, ApiConsumes, ApiOperation, ApiTags } from "@nestjs/swagger";
|
||||||
|
|
||||||
|
import { UploadMultipleFileDto, UploadSingleFileDto } from "./DTO/upload-file.dto";
|
||||||
|
import { UploaderService } from "./uploader.service";
|
||||||
|
import { IFile } from "../utils/interfaces/IFile";
|
||||||
|
|
||||||
|
@ApiTags("Uploader")
|
||||||
|
@Controller("uploader")
|
||||||
|
// @AuthGuards()
|
||||||
|
export class UploaderController {
|
||||||
|
constructor(private readonly uploaderService: UploaderService) {}
|
||||||
|
|
||||||
|
@ApiOperation({ summary: "Uploads a single file" })
|
||||||
|
@ApiConsumes("multipart/form-data")
|
||||||
|
@UseInterceptors(FileInterceptor("file"))
|
||||||
|
@ApiBody({ type: UploadSingleFileDto })
|
||||||
|
@Post("single-file")
|
||||||
|
uploadFile(@UploadedFile() file: IFile) {
|
||||||
|
return this.uploaderService.upload(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation({ summary: "Uploads multiple files" })
|
||||||
|
@ApiConsumes("multipart/form-data")
|
||||||
|
@UseInterceptors(FilesInterceptor("files"))
|
||||||
|
@ApiBody({ type: UploadMultipleFileDto })
|
||||||
|
@Post("multi-file")
|
||||||
|
uploadFiles(@UploadedFiles() files: IFile[]) {
|
||||||
|
return this.uploaderService.uploadMultiple(files);
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+14
@@ -0,0 +1,14 @@
|
|||||||
|
import { Module } from "@nestjs/common";
|
||||||
|
|
||||||
|
import { UploaderController } from "./uploader.controller";
|
||||||
|
import { UploaderService } from "./uploader.service";
|
||||||
|
import { S3Service } from "../utils/providers/s3.service";
|
||||||
|
import { UtilsModule } from "../utils/utils.module";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [UtilsModule],
|
||||||
|
providers: [UploaderService, S3Service],
|
||||||
|
controllers: [UploaderController],
|
||||||
|
exports: [UploaderService],
|
||||||
|
})
|
||||||
|
export class UploaderModule {}
|
||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
|
||||||
|
import { IFile } from "../utils/interfaces/IFile";
|
||||||
|
import { S3Service } from "../utils/providers/s3.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UploaderService {
|
||||||
|
constructor(private s3Service: S3Service) {}
|
||||||
|
|
||||||
|
async upload(file: IFile) {
|
||||||
|
return await this.s3Service.upload(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
async uploadMultiple(files: IFile[]) {
|
||||||
|
// const uploadPromises = files.map((file) => this.s3Service.upload(file));
|
||||||
|
|
||||||
|
// return await Promise.all(uploadPromises);
|
||||||
|
return this.s3Service.uploadMultiple(files);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,7 +43,6 @@ export class SmsService {
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
console.log(data, "================");
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user