add business owner assignment
This commit is contained in:
@@ -17,6 +17,7 @@ import { Roles } from '../auth/decorators/roles.decorator';
|
|||||||
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
|
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
|
||||||
import { RolesGuard } from '../auth/guards/roles.guard';
|
import { RolesGuard } from '../auth/guards/roles.guard';
|
||||||
import { BusinessesService } from './businesses.service';
|
import { BusinessesService } from './businesses.service';
|
||||||
|
import { AssignBusinessOwnerDto } from './dto/assign-business-owner.dto';
|
||||||
import { CreateBusinessDto } from './dto/create-business.dto';
|
import { CreateBusinessDto } from './dto/create-business.dto';
|
||||||
import { UpdateBusinessDto } from './dto/update-business.dto';
|
import { UpdateBusinessDto } from './dto/update-business.dto';
|
||||||
|
|
||||||
@@ -50,6 +51,16 @@ export class BusinessesController {
|
|||||||
return this.service.create(payload);
|
return this.service.create(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post(':id/assign-owner')
|
||||||
|
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||||
|
@Roles(UserRole.ADMIN)
|
||||||
|
assignOwner(
|
||||||
|
@Param('id') id: string,
|
||||||
|
@Body() payload: AssignBusinessOwnerDto,
|
||||||
|
): Promise<BusinessEntity> {
|
||||||
|
return this.service.assignOwner(id, payload);
|
||||||
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||||
@Roles(UserRole.ADMIN, UserRole.BUSINESS_OWNER)
|
@Roles(UserRole.ADMIN, UserRole.BUSINESS_OWNER)
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ import { Module } from '@nestjs/common';
|
|||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { BusinessCategoryEntity } from '../../entities/business-category.entity';
|
import { BusinessCategoryEntity } from '../../entities/business-category.entity';
|
||||||
import { BusinessEntity } from '../../entities/business.entity';
|
import { BusinessEntity } from '../../entities/business.entity';
|
||||||
|
import { UserEntity } from '../../entities/user.entity';
|
||||||
import { AuthModule } from '../auth/auth.module';
|
import { AuthModule } from '../auth/auth.module';
|
||||||
import { BusinessesController } from './businesses.controller';
|
import { BusinessesController } from './businesses.controller';
|
||||||
import { BusinessesService } from './businesses.service';
|
import { BusinessesService } from './businesses.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
TypeOrmModule.forFeature([BusinessEntity, BusinessCategoryEntity]),
|
TypeOrmModule.forFeature([BusinessEntity, BusinessCategoryEntity, UserEntity]),
|
||||||
AuthModule,
|
AuthModule,
|
||||||
],
|
],
|
||||||
controllers: [BusinessesController],
|
controllers: [BusinessesController],
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
BadRequestException,
|
||||||
ConflictException,
|
ConflictException,
|
||||||
ForbiddenException,
|
ForbiddenException,
|
||||||
Injectable,
|
Injectable,
|
||||||
@@ -8,8 +9,9 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { BusinessCategoryEntity } from '../../entities/business-category.entity';
|
import { BusinessCategoryEntity } from '../../entities/business-category.entity';
|
||||||
import { BusinessEntity } from '../../entities/business.entity';
|
import { BusinessEntity } from '../../entities/business.entity';
|
||||||
import { UserRole } from '../../entities/user.entity';
|
import { UserEntity, UserRole } from '../../entities/user.entity';
|
||||||
import { AuthUser } from '../auth/auth.types';
|
import { AuthUser } from '../auth/auth.types';
|
||||||
|
import { AssignBusinessOwnerDto } from './dto/assign-business-owner.dto';
|
||||||
import { CreateBusinessDto } from './dto/create-business.dto';
|
import { CreateBusinessDto } from './dto/create-business.dto';
|
||||||
import { UpdateBusinessDto } from './dto/update-business.dto';
|
import { UpdateBusinessDto } from './dto/update-business.dto';
|
||||||
|
|
||||||
@@ -25,6 +27,8 @@ export class BusinessesService {
|
|||||||
private readonly repo: Repository<BusinessEntity>,
|
private readonly repo: Repository<BusinessEntity>,
|
||||||
@InjectRepository(BusinessCategoryEntity)
|
@InjectRepository(BusinessCategoryEntity)
|
||||||
private readonly categoryRepo: Repository<BusinessCategoryEntity>,
|
private readonly categoryRepo: Repository<BusinessCategoryEntity>,
|
||||||
|
@InjectRepository(UserEntity)
|
||||||
|
private readonly userRepo: Repository<UserEntity>,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async findAll(filters: FindAllFilters): Promise<BusinessEntity[]> {
|
async findAll(filters: FindAllFilters): Promise<BusinessEntity[]> {
|
||||||
@@ -113,6 +117,36 @@ export class BusinessesService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async assignOwner(
|
||||||
|
id: string,
|
||||||
|
dto: AssignBusinessOwnerDto,
|
||||||
|
): Promise<BusinessEntity> {
|
||||||
|
const business = await this.findOne(id);
|
||||||
|
const mobile = this.normalizeMobile(dto.mobile);
|
||||||
|
|
||||||
|
let user = await this.userRepo.findOne({ where: { mobile } });
|
||||||
|
if (!user) {
|
||||||
|
user = this.userRepo.create({
|
||||||
|
mobile,
|
||||||
|
fullName: dto.fullName ?? null,
|
||||||
|
role: UserRole.BUSINESS_OWNER,
|
||||||
|
isActive: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (user.role !== UserRole.ADMIN) {
|
||||||
|
user.role = UserRole.BUSINESS_OWNER;
|
||||||
|
}
|
||||||
|
if (dto.fullName !== undefined) {
|
||||||
|
user.fullName = dto.fullName;
|
||||||
|
}
|
||||||
|
user.isActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const savedUser = await this.userRepo.save(user);
|
||||||
|
business.ownerId = savedUser.id;
|
||||||
|
return this.repo.save(business);
|
||||||
|
}
|
||||||
|
|
||||||
private async ensureCategoryExists(categoryId: string): Promise<void> {
|
private async ensureCategoryExists(categoryId: string): Promise<void> {
|
||||||
const category = await this.categoryRepo.findOne({ where: { id: categoryId } });
|
const category = await this.categoryRepo.findOne({ where: { id: categoryId } });
|
||||||
if (!category) {
|
if (!category) {
|
||||||
@@ -120,6 +154,14 @@ export class BusinessesService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private normalizeMobile(mobile: string): string {
|
||||||
|
const normalized = String(mobile ?? '').trim();
|
||||||
|
if (!/^(\+?\d{10,15}|09\d{9})$/.test(normalized)) {
|
||||||
|
throw new BadRequestException('Invalid mobile number');
|
||||||
|
}
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
private assertCanUpdateBusiness(
|
private assertCanUpdateBusiness(
|
||||||
business: BusinessEntity,
|
business: BusinessEntity,
|
||||||
payload: UpdateBusinessDto,
|
payload: UpdateBusinessDto,
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export class AssignBusinessOwnerDto {
|
||||||
|
mobile!: string;
|
||||||
|
fullName?: string | null;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user