This commit is contained in:
2026-04-14 14:22:04 +03:30
parent 510fbea3b1
commit eca144a6c6
19 changed files with 317 additions and 23 deletions
@@ -0,0 +1,24 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class REeseller1776149212591 implements MigrationInterface {
name = 'REeseller1776149212591'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "reward_withdraw_request" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "requestedAmount" numeric(10,2), "paidAt" TIMESTAMP, "transactionId" character varying(255), "userId" uuid, CONSTRAINT "PK_8d5dc28a526ec3886c88347ef3f" PRIMARY KEY ("id"))`);
await queryRunner.query(`ALTER TYPE "public"."permission_name_enum" RENAME TO "permission_name_enum_old"`);
await queryRunner.query(`CREATE TYPE "public"."permission_name_enum" AS ENUM('services', 'customers', 'agents', 'developers', 'invoices', 'transactions', 'discounts', 'admins', 'tickets', 'criticisms', 'contacts_us', 'advertisements', 'announcements', 'blogs', 'learnings', 'logs', 'settings', 'bank_accounts', 'payments', 'manage_sso_clients', 'support_plan', 'dmenu', 'dkala', 'dpage', 'dmail', 'reseller')`);
await queryRunner.query(`ALTER TABLE "permission" ALTER COLUMN "name" TYPE "public"."permission_name_enum" USING "name"::"text"::"public"."permission_name_enum"`);
await queryRunner.query(`DROP TYPE "public"."permission_name_enum_old"`);
await queryRunner.query(`ALTER TABLE "reward_withdraw_request" ADD CONSTRAINT "FK_047e95b65bc9335c3b04aa35452" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "reward_withdraw_request" DROP CONSTRAINT "FK_047e95b65bc9335c3b04aa35452"`);
await queryRunner.query(`CREATE TYPE "public"."permission_name_enum_old" AS ENUM('services', 'customers', 'agents', 'developers', 'invoices', 'transactions', 'discounts', 'admins', 'tickets', 'criticisms', 'contacts_us', 'advertisements', 'announcements', 'blogs', 'learnings', 'logs', 'settings', 'bank_accounts', 'payments', 'manage_sso_clients', 'support_plan', 'dmenu', 'dkala', 'dpage', 'dmail')`);
await queryRunner.query(`ALTER TABLE "permission" ALTER COLUMN "name" TYPE "public"."permission_name_enum_old" USING "name"::"text"::"public"."permission_name_enum_old"`);
await queryRunner.query(`DROP TYPE "public"."permission_name_enum"`);
await queryRunner.query(`ALTER TYPE "public"."permission_name_enum_old" RENAME TO "permission_name_enum"`);
await queryRunner.query(`DROP TABLE "reward_withdraw_request"`);
}
}
@@ -8,5 +8,8 @@ import { ResellerRouteGuard } from "../../modules/auth/guards/reseller.guard";
// import { RoleGuard } from "../../modules/auth/guards/role.guard"; // import { RoleGuard } from "../../modules/auth/guards/role.guard";
export function AuthGuards() { export function AuthGuards() {
return applyDecorators(UseGuards(JwtAuthGuard, PermissionsGuard, AdminRouteGuard,ResellerRouteGuard), ApiBearerAuth("authorization")); return applyDecorators(UseGuards(
JwtAuthGuard, PermissionsGuard,
AdminRouteGuard, ResellerRouteGuard
), ApiBearerAuth("authorization"));
} }
+9 -4
View File
@@ -1,25 +1,30 @@
import { CanActivate, ExecutionContext, ForbiddenException, Injectable } from "@nestjs/common"; import { CanActivate, ExecutionContext, ForbiddenException, Injectable } from "@nestjs/common";
import { FastifyRequest } from "fastify"; import { FastifyRequest } from "fastify";
import { AuthMessage } from "../../../common/enums/message.enum"; import { AuthMessage } from "../../../common/enums/message.enum";
import { Reflector } from "@nestjs/core"; import { Reflector } from "@nestjs/core";
import { RESELLER_ROUTE } from "../../../common/decorators/reseller.decorator"; import { RESELLER_ROUTE } from "../../../common/decorators/reseller.decorator";
@Injectable() @Injectable()
export class ResellerRouteGuard implements CanActivate { export class ResellerRouteGuard implements CanActivate {
constructor(private reflector: Reflector) {} constructor(private reflector: Reflector) { }
canActivate(context: ExecutionContext): boolean { canActivate(context: ExecutionContext): boolean {
const requiredReseller = this.reflector.getAllAndOverride<boolean>(RESELLER_ROUTE, [context.getHandler(), context.getClass()]); const requiredReseller = this.reflector.getAllAndOverride<boolean>(RESELLER_ROUTE,
[context.getHandler(), context.getClass()]);
if (!requiredReseller) return true; if (!requiredReseller) return true;
console.log('hi')
const req = context.switchToHttp().getRequest<FastifyRequest>(); const req = context.switchToHttp().getRequest<FastifyRequest>();
const user = req.user; const user = req.user;
console.log(user)
if (!user) throw new ForbiddenException(AuthMessage.UNAUTHORIZED_ACCESS); if (!user) throw new ForbiddenException(AuthMessage.UNAUTHORIZED_ACCESS);
if (!user.isReseller) throw new ForbiddenException(AuthMessage.UNAUTHORIZED_ACCESS); // if (!user.isReseller) throw new ForbiddenException(AuthMessage.UNAUTHORIZED_ACCESS);
return true; return true;
} }
@@ -41,6 +41,7 @@ import { InvoicesRepository } from "../repositories/invoices.repository";
import { DkalaService } from "../../dkala/providers/dkala.service"; import { DkalaService } from "../../dkala/providers/dkala.service";
import { DPageService } from "../../dpage/dpage.service"; import { DPageService } from "../../dpage/dpage.service";
import { randomInt } from "crypto"; import { randomInt } from "crypto";
import { SearchResellerInvoicesQueryDto } from "../../reseller/dto/search-reseller-invoices.dto";
@Injectable() @Injectable()
export class InvoicesService { export class InvoicesService {
private readonly logger = new Logger(InvoicesService.name); private readonly logger = new Logger(InvoicesService.name);
@@ -1470,4 +1471,13 @@ export class InvoicesService {
}, },
); );
} }
//*********************************** */
async findInvoicesByCustomerIds(custmerIds: string[], query: SearchResellerInvoicesQueryDto) {
const [data, count] = await this.invoiceRepository.findPaginatedListByUserIds(query, custmerIds)
return { data, count, paginate: true };
}
} }
@@ -63,4 +63,39 @@ export class InvoicesRepository extends Repository<Invoice> {
return await queryBuilder.getManyAndCount(); return await queryBuilder.getManyAndCount();
} }
async findPaginatedListByUserIds(queryDto: InvoicesSearchQueryDto, userIds: string[]) {
const { limit, skip } = PaginationUtils(queryDto);
const queryBuilder = this.createQueryBuilder("invoice");
console.log(userIds)
queryBuilder
.leftJoin("invoice.user", "user")
.addSelect(["user.id", "user.firstName", "user.lastName", "user.email", "user.phone"])
// .where("user.id IN (:...userIds)", { userIds });
if (queryDto.status) {
queryBuilder.andWhere("invoice.status = :status", { status: queryDto.status });
}
if (queryDto.since) {
queryBuilder.andWhere("(invoice.createdAt >= :since OR invoice.dueDate >= :since OR invoice.paidAt >= :since)", {
since: new Date(queryDto.since),
});
}
if (queryDto.to) {
queryBuilder.andWhere("(invoice.createdAt <= :to OR invoice.dueDate <= :to OR invoice.paidAt <= :to)", {
to: new Date(queryDto.to),
});
}
queryBuilder.orderBy("invoice.createdAt", "DESC");
queryBuilder.skip(skip);
queryBuilder.take(limit);
return await queryBuilder.getManyAndCount();
}
} }
@@ -2,7 +2,7 @@ import { randomBytes } from "node:crypto";
import { BadRequestException, Injectable } from "@nestjs/common"; import { BadRequestException, Injectable } from "@nestjs/common";
import Decimal from "decimal.js"; import Decimal from "decimal.js";
import { QueryRunner } from "typeorm"; import { QueryRunner, In } from "typeorm";
import { ReferralMessage, UserMessage } from "../../../common/enums/message.enum"; import { ReferralMessage, UserMessage } from "../../../common/enums/message.enum";
import { User } from "../../users/entities/user.entity"; import { User } from "../../users/entities/user.entity";
@@ -11,6 +11,8 @@ import { ReferralStatus } from "../enums/referral-status.enum";
import { ReferralCodesRepository } from "../repositories/referral-codes.repository"; import { ReferralCodesRepository } from "../repositories/referral-codes.repository";
import { ReferralRewardsRepository } from "../repositories/referral-rewards.repository"; import { ReferralRewardsRepository } from "../repositories/referral-rewards.repository";
import { ReferralsRepository } from "../repositories/referrals.repository"; import { ReferralsRepository } from "../repositories/referrals.repository";
import { SearchCustomersDto } from "../../users/DTO/search-customers.dto";
import { SearchRewardsRequestQueryDto } from "../../reseller/dto/search-reward-requests.dto";
@Injectable() @Injectable()
export class ReferralsService { export class ReferralsService {
private MAX_ATTEMPTS = 10; private MAX_ATTEMPTS = 10;
@@ -18,7 +20,7 @@ export class ReferralsService {
private readonly referralsRepository: ReferralsRepository, private readonly referralsRepository: ReferralsRepository,
private readonly referralCodesRepository: ReferralCodesRepository, private readonly referralCodesRepository: ReferralCodesRepository,
private readonly referralRewardsRepository: ReferralRewardsRepository, private readonly referralRewardsRepository: ReferralRewardsRepository,
) {} ) { }
async generateReferralCode(userId: string, queryRunner: QueryRunner) { async generateReferralCode(userId: string, queryRunner: QueryRunner) {
const existReferralCode = await queryRunner.manager.findOneBy(this.referralCodesRepository.target, { user: { id: userId } }); const existReferralCode = await queryRunner.manager.findOneBy(this.referralCodesRepository.target, { user: { id: userId } });
@@ -118,8 +120,40 @@ export class ReferralsService {
return reward; return reward;
} }
//*********************************** */
async findPaginatedReferedUsers(userIds: string[], query: SearchCustomersDto) {
const [data, count] = await this.referralsRepository.findPaginatedList(userIds, query)
return { data, count, paginate: true };
}
async findReferedUsersIds(userIds: string[]) {
const referedUSers = await this.referralsRepository.find({
where: {
referrer: {
id: In(userIds)
}
},
select: {
id: true
}
})
return referedUSers.map(u => u.id)
}
//*********************************** */ //*********************************** */
private generateRandomCode(): string { private generateRandomCode(): string {
return randomBytes(6).toString("hex"); return randomBytes(6).toString("hex");
} }
//*********************************** */
async findRewards(userIds: string[], query: SearchRewardsRequestQueryDto) {
const [data, count] = await this.referralRewardsRepository.findPaginatedList(userIds, query);
return { data, count, paginate: true };
}
} }
+1 -1
View File
@@ -15,4 +15,4 @@ import { ReferralsRepository } from "./repositories/referrals.repository";
controllers: [], controllers: [],
exports: [ReferralsService], exports: [ReferralsService],
}) })
export class ReferralsModule {} export class ReferralsModule { }
@@ -3,10 +3,27 @@ import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm"; import { Repository } from "typeorm";
import { ReferralReward } from "../entities/referral-reward.entity"; import { ReferralReward } from "../entities/referral-reward.entity";
import { PaginationUtils } from "../../utils/providers/pagination.utils";
import { SearchRewardsRequestQueryDto } from "../../reseller/dto/search-reward-requests.dto";
@Injectable() @Injectable()
export class ReferralRewardsRepository extends Repository<ReferralReward> { export class ReferralRewardsRepository extends Repository<ReferralReward> {
constructor(@InjectRepository(ReferralReward) repository: Repository<ReferralReward>) { constructor(@InjectRepository(ReferralReward) repository: Repository<ReferralReward>) {
super(repository.target, repository.manager, repository.queryRunner); super(repository.target, repository.manager, repository.queryRunner);
}
async findPaginatedList(userIds: string[], queryDto: SearchRewardsRequestQueryDto) {
const { limit, skip } = PaginationUtils(queryDto);
const qb = this.createQueryBuilder("referral")
.where("referral.referrerId IN (:...userIds)", { userIds })
.leftJoinAndSelect("referral.referrer", "referrer")
.leftJoinAndSelect("referral.referredUser", "referred")
.orderBy("referral.createdAt", "DESC")
.skip(skip)
.take(limit);
return qb.getManyAndCount();
} }
} }
@@ -1,12 +1,27 @@
import { Injectable } from "@nestjs/common"; import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm"; import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm"; import { Repository } from "typeorm";
import { Referral } from "../entities/referral.entity"; import { Referral } from "../entities/referral.entity";
import { PaginationUtils } from "../../utils/providers/pagination.utils";
import { SearchCustomersQueryDto } from "../../reseller/dto/search-customers.dto";
@Injectable() @Injectable()
export class ReferralsRepository extends Repository<Referral> { export class ReferralsRepository extends Repository<Referral> {
constructor(@InjectRepository(Referral) repository: Repository<Referral>) { constructor(@InjectRepository(Referral) repository: Repository<Referral>) {
super(repository.target, repository.manager, repository.queryRunner); super(repository.target, repository.manager, repository.queryRunner);
} }
async findPaginatedList(userIds: string[], queryDto: SearchCustomersQueryDto) {
const { limit, skip } = PaginationUtils(queryDto);
const qb = this.createQueryBuilder("referral")
.where("referral.referrerId IN (:...userIds)", { userIds })
.leftJoinAndSelect("referral.referrer", "referrer")
.leftJoinAndSelect("referral.referredUser", "referred")
.orderBy("referral.createdAt", "DESC")
.skip(skip)
.take(limit);
return qb.getManyAndCount();
}
} }
@@ -1,9 +1,11 @@
import { ApiProperty } from "@nestjs/swagger"; import { ApiProperty } from "@nestjs/swagger";
import { IsNotEmpty, IsString } from "class-validator"; import { IsMobilePhone, IsNotEmpty, Length } from "class-validator";
import { AuthMessage } from "../../../common/enums/message.enum";
export class CreateResellerAgentDto { export class CreateResellerAgentDto {
@IsNotEmpty() @IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
@IsString() @IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
@ApiProperty() @Length(11, 11, { message: AuthMessage.PHONE_SHOULD_BE_11_DIGIT })
userId: string; @ApiProperty({ description: "phone number", default: "09922320740" })
phone: string;
} }
@@ -0,0 +1,3 @@
import { PaginationDto } from "../../../common/DTO/pagination.dto";
export class SearchCustomersQueryDto extends PaginationDto { }
@@ -0,0 +1,3 @@
import { PaginationDto } from "../../../common/DTO/pagination.dto";
export class SearchResellerInvoicesQueryDto extends PaginationDto { }
@@ -0,0 +1,5 @@
import { PaginationDto } from "../../../common/DTO/pagination.dto";
export class SearchRewardsRequestQueryDto extends PaginationDto {
}
@@ -0,0 +1,20 @@
import Decimal from "decimal.js";
import { Column, Entity, ManyToOne } from "typeorm";
import { BaseEntity } from "../../../common/entities/base.entity";
import { DecimalTransformer } from "../../../common/transformers/decimal.transformer";
import { User } from "../../users/entities/user.entity";
@Entity()
export class RewardWithdrawRequest extends BaseEntity {
@ManyToOne(() => User, (user) => user.referralRewards)
user: User;
@Column({ type: "decimal", precision: 10, scale: 2, nullable: true, transformer: new DecimalTransformer() })
requestedAmount?: Decimal;
@Column({ type: "timestamp", nullable: true })
paidAt: Date;
@Column({ type: "varchar", length: 255, nullable: true })
transactionId?: string;
}
@@ -0,0 +1,23 @@
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { RewardWithdrawRequest } from "../entities/rewards-withdraw-request.entity";
import { SearchRewardsRequestQueryDto } from "../dto/search-reward-requests.dto";
import { PaginationUtils } from "../../utils/providers/pagination.utils";
@Injectable()
export class WithdrawRequestRepository extends Repository<RewardWithdrawRequest> {
constructor(@InjectRepository(RewardWithdrawRequest) repository: Repository<RewardWithdrawRequest>) {
super(repository.target, repository.manager, repository.queryRunner);
}
async findPaginatedList(queryDto: SearchRewardsRequestQueryDto) {
const { limit, skip } = PaginationUtils(queryDto);
const queryBuilder = this.createQueryBuilder("request")
.leftJoinAndSelect("request.user", "user")
.orderBy("ticket.createdAt", "DESC");
return queryBuilder.skip(skip).take(limit).getManyAndCount();
}
}
+42 -5
View File
@@ -1,4 +1,4 @@
import { Controller, Get, Post, Body, Delete } from '@nestjs/common'; import { Controller, Get, Post, Body, Delete, Param, Query } from '@nestjs/common';
import { ResellerService } from './reseller.service'; import { ResellerService } from './reseller.service';
import { ApiOperation } from '@nestjs/swagger'; import { ApiOperation } from '@nestjs/swagger';
import { PermissionsDec } from '../../common/decorators/permission.decorator'; import { PermissionsDec } from '../../common/decorators/permission.decorator';
@@ -9,6 +9,9 @@ import { AdminRoute } from '../../common/decorators/admin.decorator';
import { ResellerRoute } from '../../common/decorators/reseller.decorator'; import { ResellerRoute } from '../../common/decorators/reseller.decorator';
import { UserDec } from '../../common/decorators/user.decorator'; import { UserDec } from '../../common/decorators/user.decorator';
import { CreateResellerAgentDto } from './dto/create-reseller-agent.dto'; import { CreateResellerAgentDto } from './dto/create-reseller-agent.dto';
import { SearchRewardsRequestQueryDto } from './dto/search-reward-requests.dto';
import { SearchCustomersDto } from '../users/DTO/search-customers.dto';
import { SearchResellerInvoicesQueryDto } from './dto/search-reseller-invoices.dto';
@Controller('reseller') @Controller('reseller')
@AuthGuards() @AuthGuards()
@@ -34,6 +37,16 @@ export class ResellerController {
return this.resellerService.findAll() return this.resellerService.findAll()
} }
//=========== Reward Requests =========
@ApiOperation({ summary: "get reseller reward requests ==> admin route" })
@AdminRoute()
@PermissionsDec(PermissionEnum.RESELLER)
@Get('reward/request')
getRewardRequests() {
return this.resellerService.findAll()
}
// =========== Reseller-->Agent ============= // =========== Reseller-->Agent =============
@ApiOperation({ summary: "get Reseller agents ==> reseller route" }) @ApiOperation({ summary: "get Reseller agents ==> reseller route" })
@@ -47,14 +60,38 @@ export class ResellerController {
@ResellerRoute() @ResellerRoute()
@Post('agents') @Post('agents')
createResellerAgent(@UserDec("id") userId: string, @Body() dto: CreateResellerAgentDto) { createResellerAgent(@UserDec("id") userId: string, @Body() dto: CreateResellerAgentDto) {
return this.resellerService.createResellerAgent(userId, dto.userId) return this.resellerService.createResellerAgent(userId, dto.phone)
} }
@ApiOperation({ summary: "Remove Reseller agent ==> reseller route" }) @ApiOperation({ summary: "Remove Reseller agent ==> reseller route" })
@ResellerRoute() @ResellerRoute()
@Delete('agents') @Delete('agents/:agentId')
deleteResellerAgent(@UserDec("id") userId: string, @Body() dto: CreateResellerAgentDto) { deleteResellerAgent(@UserDec("id") userId: string, @Param('agentId') agentId: string) {
return this.resellerService.removeResellerAgent(userId, dto.userId) return this.resellerService.removeResellerAgent(userId, agentId)
}
// ============ Customers =============
@ApiOperation({ summary: "get Reseller Customers ==> reseller route" })
@ResellerRoute()
@Get('customers')
getCustomers(@UserDec("id") userId: string, @Query() dto: SearchCustomersDto) {
return this.resellerService.findResellerCustomers(userId, dto)
}
// ============ Invoice =============
@ApiOperation({ summary: "get Reseller Customers Invoices==> reseller route" })
@ResellerRoute()
@Get('invoices')
getCustomerInvoices(@UserDec("id") userId: string, @Query() query: SearchResellerInvoicesQueryDto) {
return this.resellerService.findResellerCustomersInvoices(userId, query)
}
// ============ Rewards =============
@ApiOperation({ summary: "get Reseller Agents Rewards==> reseller route" })
@ResellerRoute()
@Get('rewards')
getResellerAgentsRewards(@UserDec("id") userId: string, @Query() query: SearchRewardsRequestQueryDto) {
return this.resellerService.findResellerAgentsRewards(userId, query)
} }
} }
+9 -2
View File
@@ -5,10 +5,17 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { Reseller } from './entities/reseller.entity'; import { Reseller } from './entities/reseller.entity';
import { ResellerRepository } from './repositories/reseller.repository'; import { ResellerRepository } from './repositories/reseller.repository';
import { UsersModule } from '../users/users.module'; import { UsersModule } from '../users/users.module';
import { ReferralsModule } from '../referrals/referrals.module';
import { InvoicesModule } from '../invoices/invoices.module';
import { RewardWithdrawRequest } from "../reseller/entities/rewards-withdraw-request.entity";
import { WithdrawRequestRepository } from './repositories/withdraw-request.repository';
@Module({ @Module({
imports: [TypeOrmModule.forFeature([Reseller]), UsersModule], imports: [TypeOrmModule.forFeature([Reseller, RewardWithdrawRequest]),
UsersModule,
ReferralsModule,
InvoicesModule],
controllers: [ResellerController], controllers: [ResellerController],
providers: [ResellerService, ResellerRepository], providers: [ResellerService, ResellerRepository, WithdrawRequestRepository],
}) })
export class ResellerModule { } export class ResellerModule { }
+49 -2
View File
@@ -3,12 +3,21 @@ import { UsersService } from '../users/providers/users.service';
import { CreateResellerDto } from './dto/create-reseller.dto'; import { CreateResellerDto } from './dto/create-reseller.dto';
import { ResellerRepository } from './repositories/reseller.repository'; import { ResellerRepository } from './repositories/reseller.repository';
import { AuthMessage } from '../../common/enums/message.enum'; import { AuthMessage } from '../../common/enums/message.enum';
import { ReferralsService } from '../referrals/providers/referrals.service';
import { InvoicesService } from '../invoices/providers/invoices.service';
import { SearchRewardsRequestQueryDto } from './dto/search-reward-requests.dto';
import { WithdrawRequestRepository } from './repositories/withdraw-request.repository';
import { SearchCustomersQueryDto } from './dto/search-customers.dto';
import { SearchResellerInvoicesQueryDto } from './dto/search-reseller-invoices.dto';
@Injectable() @Injectable()
export class ResellerService { export class ResellerService {
constructor( constructor(
private readonly usersService: UsersService, private readonly usersService: UsersService,
private readonly referralService: ReferralsService,
private readonly resellerRepository: ResellerRepository, private readonly resellerRepository: ResellerRepository,
private readonly invoicesService: InvoicesService,
private readonly withdrawRequestRepository: WithdrawRequestRepository,
) { } ) { }
async create(dto: CreateResellerDto) { async create(dto: CreateResellerDto) {
@@ -44,6 +53,7 @@ export class ResellerService {
return reseller.agents return reseller.agents
} }
async FindOneOrFailByUserId(userId: string) { async FindOneOrFailByUserId(userId: string) {
const reseller = await this.resellerRepository.findOne({ const reseller = await this.resellerRepository.findOne({
where: { owner: { id: userId } }, where: { owner: { id: userId } },
@@ -57,10 +67,14 @@ export class ResellerService {
return reseller return reseller
} }
async createResellerAgent(userId: string, userTobeAgent: string) { async createResellerAgent(userId: string, userTobeAgentPhone: string) {
const reseller = await this.FindOneOrFailByUserId(userId) const reseller = await this.FindOneOrFailByUserId(userId)
const { user } = await this.usersService.findOneById(userTobeAgent) const user = await this.usersService.findOneWithPhone(userTobeAgentPhone)
if (!user) {
throw new NotFoundException(AuthMessage.USER_NOT_FOUND)
}
user.reseller = reseller user.reseller = reseller
@@ -80,4 +94,37 @@ export class ResellerService {
return user return user
} }
async findResellerCustomers(userId: string, query: SearchCustomersQueryDto) {
const reselller = await this.FindOneOrFailByUserId(userId)
const agentIds = reselller.agents.map(ag => ag.id)
return this.referralService.findPaginatedReferedUsers(agentIds, query)
}
async findResellerCustomersInvoices(userId: string, query: SearchResellerInvoicesQueryDto) {
const reselller = await this.FindOneOrFailByUserId(userId)
const agentIds = reselller.agents.map(ag => ag.id)
const customerIds = await this.referralService.findReferedUsersIds(agentIds)
return this.invoicesService.findInvoicesByCustomerIds(customerIds, query)
}
async findResellerAgentsRewards(userId: string, query: SearchRewardsRequestQueryDto) {
const reselller = await this.FindOneOrFailByUserId(userId)
const agentIds = reselller.agents.map(ag => ag.id)
return this.referralService.findRewards(agentIds, query)
}
async getRewrdsRequests(queryDto: SearchRewardsRequestQueryDto) {
const [requests, count] = await this.withdrawRequestRepository.findPaginatedList(queryDto);
return { requests, count, paginate: true };
}
} }
@@ -419,4 +419,8 @@ export class UsersService {
async save(user: User) { async save(user: User) {
return this.userRepository.save(user) return this.userRepository.save(user)
} }
/**************************** */
} }