diff --git a/src/common/enums/message.enum.ts b/src/common/enums/message.enum.ts index a73edf8..e982997 100644 --- a/src/common/enums/message.enum.ts +++ b/src/common/enums/message.enum.ts @@ -503,3 +503,9 @@ export const enum RealUserMessage { export const enum LegalUserMessage { LEGAL_DATA_EXIST = "اطلاعات حقوقی این کاربر وجود دارد", } + +export const enum UserQuickAccessMessage { + USER_SUBS_NOT_FOUND = "کاربر اشتراک فعالی برای این سرویس ندارد", + QUICK_ACCESS_LIMIT_REACHED = "حداکثر تعداد دسترسی سریع برای این کاربر ایجاد شده است", + QUICK_ACCESS_EXIST = "این دسترسی سریع قبلا ایجاد شده است", +} diff --git a/src/modules/danak-services/entities/danak-service.entity.ts b/src/modules/danak-services/entities/danak-service.entity.ts index e9f81d8..ea543b3 100644 --- a/src/modules/danak-services/entities/danak-service.entity.ts +++ b/src/modules/danak-services/entities/danak-service.entity.ts @@ -7,6 +7,7 @@ import { BaseEntity } from "../../../common/entities/base.entity"; import { Ads } from "../../ads/entities/ads.entity"; import { Announcement } from "../../announcements/entities/announcement.entity"; import { SubscriptionPlan } from "../../subscriptions/entities/subscription.entity"; +import { UserQuickAccess } from "../../subscriptions/entities/user-quick-access.entity"; import { Ticket } from "../../tickets/entities/ticket.entity"; import { ServicesLanguage } from "../enums/services-language.enum"; @@ -76,6 +77,8 @@ export class DanakService extends BaseEntity { @OneToMany(() => DanakServiceReview, (danakServiceReview) => danakServiceReview.service) reviews: DanakServiceReview[]; + @OneToMany(() => UserQuickAccess, (quickAccess) => quickAccess.service) + quickAccess: UserQuickAccess[]; // @ManyToMany(() => Discount, (discount) => discount.services, { nullable: true }) // discounts?: Discount[]; } diff --git a/src/modules/subscriptions/entities/user-quick-access.entity.ts b/src/modules/subscriptions/entities/user-quick-access.entity.ts new file mode 100644 index 0000000..74ee7e7 --- /dev/null +++ b/src/modules/subscriptions/entities/user-quick-access.entity.ts @@ -0,0 +1,18 @@ +import { Column, Entity, ManyToOne, Unique } from "typeorm"; + +import { BaseEntity } from "../../../common/entities/base.entity"; +import { DanakService } from "../../danak-services/entities/danak-service.entity"; +import { User } from "../../users/entities/user.entity"; + +@Entity() +@Unique(["user", "service"]) +export class UserQuickAccess extends BaseEntity { + @ManyToOne(() => User, (user) => user.quickAccesses, { nullable: false, onDelete: "SET NULL" }) + user: User; + + @ManyToOne(() => DanakService, { nullable: false, onDelete: "SET NULL" }) + service: DanakService; + + @Column({ type: "boolean", default: true }) + isActive: boolean; +} diff --git a/src/modules/subscriptions/providers/subscriptions.service.ts b/src/modules/subscriptions/providers/subscriptions.service.ts index 4fe90e1..21167b9 100644 --- a/src/modules/subscriptions/providers/subscriptions.service.ts +++ b/src/modules/subscriptions/providers/subscriptions.service.ts @@ -419,4 +419,19 @@ export class SubscriptionsService { const growthRate = ((currentYearCount - lastYearCount) / lastYearCount) * 100; return Math.round(growthRate * 100) / 100; } + + /********************************* */ + + async activeUserSubscription(userId: string, serviceId: string) { + const activeSubscription = await this.userSubscriptionsRepository.findOne({ + where: { + user: { id: userId }, + plan: { service: { id: serviceId } }, + status: SubscriptionStatus.ACTIVE, + }, + relations: ["plan", "plan.service"], + }); + console.log(activeSubscription); + return activeSubscription; + } } diff --git a/src/modules/subscriptions/providers/users-quick-access.service.ts b/src/modules/subscriptions/providers/users-quick-access.service.ts new file mode 100644 index 0000000..838ddef --- /dev/null +++ b/src/modules/subscriptions/providers/users-quick-access.service.ts @@ -0,0 +1,63 @@ +import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; + +import { SubscriptionsService } from "./subscriptions.service"; +import { CommonMessage, ServiceMessage, UserMessage, UserQuickAccessMessage } from "../../../common/enums/message.enum"; +import { DanakServicesService } from "../../danak-services/providers/danak-services.service"; +import { UsersService } from "../../users/providers/users.service"; +import { UserQuickAccessRepository } from "../repositories/users-quick-access.repository"; + +@Injectable() +export class UserQuickAccessService { + constructor( + private readonly quickAccessRepository: UserQuickAccessRepository, + private readonly usersService: UsersService, + private readonly danakServicesService: DanakServicesService, + private readonly subscriptionService: SubscriptionsService, + ) {} + + async addQuickAccess(userId: string, serviceId: string) { + const { user } = await this.usersService.findOneById(userId); + if (!user) throw new NotFoundException(UserMessage.USER_NOT_FOUND); + + const service = await this.danakServicesService.findServiceById(serviceId); + if (!service) throw new NotFoundException(ServiceMessage.SERVICE_NOT_EXIST); + + const activeSubscription = await this.subscriptionService.activeUserSubscription(user.id, service.id); + if (!activeSubscription) { + throw new BadRequestException(UserQuickAccessMessage.USER_SUBS_NOT_FOUND); + } + + const userQuickAccesses = await this.quickAccessRepository.count({ where: { user: { id: userId }, isActive: true } }); + if (userQuickAccesses >= 4) { + throw new BadRequestException(UserQuickAccessMessage.QUICK_ACCESS_LIMIT_REACHED); + } + + const existQuickAccess = await this.quickAccessRepository.findOne({ where: { user: { id: user.id }, service: { id: service.id } } }); + console.log(existQuickAccess); + if (existQuickAccess) throw new BadRequestException(UserQuickAccessMessage.QUICK_ACCESS_EXIST); + + const quickAccess = this.quickAccessRepository.create({ user, service }); + + await this.quickAccessRepository.save(quickAccess); + + return { + message: CommonMessage.CREATED, + quickAccess, + }; + } + + async removeQuickAccess(userId: string, serviceId: string) { + await this.quickAccessRepository.delete({ user: { id: userId }, service: { id: serviceId } }); + return { + message: CommonMessage.DELETED, + }; + } + + async getUserQuickAccess(userId: string) { + const quickAccesses = await this.quickAccessRepository.find({ + where: { user: { id: userId }, isActive: true }, + relations: ["service"], + }); + return { quickAccesses }; + } +} diff --git a/src/modules/subscriptions/repositories/users-quick-access.repository.ts b/src/modules/subscriptions/repositories/users-quick-access.repository.ts new file mode 100644 index 0000000..ba03271 --- /dev/null +++ b/src/modules/subscriptions/repositories/users-quick-access.repository.ts @@ -0,0 +1,12 @@ +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; + +import { UserQuickAccess } from "../entities/user-quick-access.entity"; + +@Injectable() +export class UserQuickAccessRepository extends Repository { + constructor(@InjectRepository(UserQuickAccess) userQuickAccessRepository: Repository) { + super(userQuickAccessRepository.target, userQuickAccessRepository.manager, userQuickAccessRepository.queryRunner); + } +} diff --git a/src/modules/subscriptions/subscriptions.controller.ts b/src/modules/subscriptions/subscriptions.controller.ts index 8d644f4..46d2b05 100644 --- a/src/modules/subscriptions/subscriptions.controller.ts +++ b/src/modules/subscriptions/subscriptions.controller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, Get, Param, Patch, Post, Query } from "@nestjs/common"; +import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from "@nestjs/common"; import { ApiOperation } from "@nestjs/swagger"; import { AddSubscriptionsToServiceDto } from "./DTO/create-subscription.dto"; @@ -8,6 +8,7 @@ import { ServiceSubsQueryDto } from "./DTO/service-subs-query.dto"; import { SubscribeServiceDto } from "./DTO/subscribe-service.dto"; import { UpdateSubscriptionPlanDto } from "./DTO/update-subscription.dto"; import { SubscriptionsService } from "./providers/subscriptions.service"; +import { UserQuickAccessService } from "./providers/users-quick-access.service"; import { AuthGuards } from "../../common/decorators/auth-guard.decorator"; import { PermissionsDec } from "../../common/decorators/permission.decorator"; import { UserDec } from "../../common/decorators/user.decorator"; @@ -16,7 +17,10 @@ import { PermissionEnum } from "../users/enums/permission.enum"; @Controller("subscriptions") export class SubscriptionsController { - constructor(private readonly subscriptionService: SubscriptionsService) {} + constructor( + private readonly subscriptionService: SubscriptionsService, + private readonly userQuickAccessService: UserQuickAccessService, + ) {} @ApiOperation({ summary: "Create a subscription plan" }) @AuthGuards() @@ -79,4 +83,25 @@ export class SubscriptionsController { subscribe(@Param() paramDto: ServiceIdParamDto, @Body() subscribeDto: SubscribeServiceDto, @UserDec("id") userId: string) { return this.subscriptionService.subscribeToPlan(paramDto.serviceId, subscribeDto, userId); } + + @ApiOperation({ summary: "add quick access a service ==> user route" }) + @AuthGuards() + @Post(":serviceId/add-quick-access") + addQuickAccess(@Param() paramDto: ServiceIdParamDto, @UserDec("id") userId: string) { + return this.userQuickAccessService.addQuickAccess(userId, paramDto.serviceId); + } + + @ApiOperation({ summary: "get quick access a service ==> user route" }) + @AuthGuards() + @Get("quick-access") + getQuickAccess(@UserDec("id") userId: string) { + return this.userQuickAccessService.getUserQuickAccess(userId); + } + + @ApiOperation({ summary: "remove quick access a service ==> user route" }) + @AuthGuards() + @Delete(":serviceId/remove-quick-access") + removeQuickAccess(@Param() paramDto: ServiceIdParamDto, @UserDec("id") userId: string) { + return this.userQuickAccessService.removeQuickAccess(userId, paramDto.serviceId); + } } diff --git a/src/modules/subscriptions/subscriptions.module.ts b/src/modules/subscriptions/subscriptions.module.ts index 7db7169..945b499 100644 --- a/src/modules/subscriptions/subscriptions.module.ts +++ b/src/modules/subscriptions/subscriptions.module.ts @@ -11,17 +11,26 @@ import { DanakServicesModule } from "../danak-services/danak-services.module"; import { InvoicesModule } from "../invoices/invoices.module"; import { UsersModule } from "../users/users.module"; import { WalletsModule } from "../wallets/wallets.module"; +import { UserQuickAccess } from "./entities/user-quick-access.entity"; +import { UserQuickAccessService } from "./providers/users-quick-access.service"; +import { UserQuickAccessRepository } from "./repositories/users-quick-access.repository"; @Module({ imports: [ - TypeOrmModule.forFeature([SubscriptionPlan, UserSubscription]), + TypeOrmModule.forFeature([SubscriptionPlan, UserSubscription, UserQuickAccess]), DanakServicesModule, UsersModule, WalletsModule, InvoicesModule, ], - providers: [SubscriptionsService, SubscriptionsPlanRepository, UserSubscriptionsRepository], + providers: [ + SubscriptionsService, + SubscriptionsPlanRepository, + UserSubscriptionsRepository, + UserQuickAccessRepository, + UserQuickAccessService, + ], controllers: [SubscriptionsController], - exports: [SubscriptionsService, TypeOrmModule, SubscriptionsPlanRepository], + exports: [SubscriptionsService, TypeOrmModule, SubscriptionsPlanRepository, UserSubscriptionsRepository], }) export class SubscriptionsModule {} diff --git a/src/modules/users/entities/user.entity.ts b/src/modules/users/entities/user.entity.ts index 086d7ca..29c8558 100644 --- a/src/modules/users/entities/user.entity.ts +++ b/src/modules/users/entities/user.entity.ts @@ -19,6 +19,7 @@ import { LearningProgress } from "../../learnings/entities/learning-progress.ent import { Notification } from "../../notifications/entities/notification.entity"; import { Payment } from "../../payments/entities/payment.entity"; import { UserSetting } from "../../settings/entities/user-setting.entity"; +import { UserQuickAccess } from "../../subscriptions/entities/user-quick-access.entity"; import { UserSubscription } from "../../subscriptions/entities/user-subscription.entity"; import { TicketMessage } from "../../tickets/entities/ticket-message.entity"; import { Ticket } from "../../tickets/entities/ticket.entity"; @@ -131,6 +132,9 @@ export class User extends BaseEntity { @ManyToMany(() => Announcement, (announcement) => announcement.users) announcements: Announcement[]; + + @OneToMany(() => UserQuickAccess, (quickAccess) => quickAccess.user) + quickAccesses: UserQuickAccess[]; } // @ManyToMany(() => DanakService, (danakService) => danakService.users)