reseller
This commit is contained in:
@@ -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"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 { }
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************** */
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user