fix: the bug in transaction list user side
This commit is contained in:
@@ -21,7 +21,7 @@ export class PaginationInterceptor implements NestInterceptor {
|
|||||||
return next.handle().pipe(
|
return next.handle().pipe(
|
||||||
map((data) => {
|
map((data) => {
|
||||||
if (data && (data.paginate || data.count)) {
|
if (data && (data.paginate || data.count)) {
|
||||||
const { count, ...response } = data;
|
const { count, paginate, ...response } = data;
|
||||||
this.logger.log(`paginate response from ${className}.${handlerName}`);
|
this.logger.log(`paginate response from ${className}.${handlerName}`);
|
||||||
const pager = this.formatPage(page, limit, count, request);
|
const pager = this.formatPage(page, limit, count, request);
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export class CompleteRegistrationDto {
|
|||||||
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
|
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
|
||||||
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
|
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
|
||||||
@Length(11, 11, { message: AuthMessage.PHONE_SHOULD_BE_11_DIGIT })
|
@Length(11, 11, { message: AuthMessage.PHONE_SHOULD_BE_11_DIGIT })
|
||||||
@ApiProperty({ description: "phone number", default: "09123456789" })
|
@ApiProperty({ description: "phone number", default: "09922320740" })
|
||||||
phone: string;
|
phone: string;
|
||||||
|
|
||||||
@ApiProperty({ description: "OTP code received via SMS", example: "56893" })
|
@ApiProperty({ description: "OTP code received via SMS", example: "56893" })
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ export class RequestOtpDto {
|
|||||||
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
|
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
|
||||||
@Length(11, 11, { message: AuthMessage.PHONE_SHOULD_BE_11_DIGIT })
|
@Length(11, 11, { message: AuthMessage.PHONE_SHOULD_BE_11_DIGIT })
|
||||||
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
|
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
|
||||||
@ApiProperty({ description: "phone number", default: "09123456789" })
|
@ApiProperty({ description: "phone number", default: "09922320740" })
|
||||||
phone: string;
|
phone: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export class VerifyOtpDto {
|
|||||||
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
|
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
|
||||||
@Length(11, 11, { message: AuthMessage.PHONE_SHOULD_BE_11_DIGIT })
|
@Length(11, 11, { message: AuthMessage.PHONE_SHOULD_BE_11_DIGIT })
|
||||||
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
|
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
|
||||||
@ApiProperty({ description: "phone number", default: "09123456789" })
|
@ApiProperty({ description: "phone number", default: "09922320740" })
|
||||||
phone: string;
|
phone: string;
|
||||||
|
|
||||||
@ApiProperty({ description: "OTP code received via SMS", example: "56893" })
|
@ApiProperty({ description: "OTP code received via SMS", example: "56893" })
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
import { Controller, Get } from "@nestjs/common";
|
import { Controller, Get } from "@nestjs/common";
|
||||||
|
import { ApiOperation } from "@nestjs/swagger";
|
||||||
|
|
||||||
import { DashboardService } from "./providers/dashboard.service";
|
import { DashboardService } from "./providers/dashboard.service";
|
||||||
import { AdminRoute } from "../../common/decorators/admin.decorator";
|
import { AdminRoute } from "../../common/decorators/admin.decorator";
|
||||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||||
|
import { UserDec } from "../../common/decorators/user.decorator";
|
||||||
|
|
||||||
@Controller("dashboards")
|
@Controller("dashboards")
|
||||||
@AuthGuards()
|
@AuthGuards()
|
||||||
@AdminRoute()
|
|
||||||
export class DashboardController {
|
export class DashboardController {
|
||||||
constructor(private readonly dashboardService: DashboardService) {}
|
constructor(private readonly dashboardService: DashboardService) {}
|
||||||
|
|
||||||
|
@ApiOperation({ summary: "Get dashboard data for admin" })
|
||||||
|
@AdminRoute()
|
||||||
@Get("reports")
|
@Get("reports")
|
||||||
async reports() {
|
reports() {
|
||||||
return this.dashboardService.reports();
|
return this.dashboardService.reports();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation({ summary: "Get dashboard data for user" })
|
||||||
|
@Get("summary")
|
||||||
|
getSummary(@UserDec("id") userId: string) {
|
||||||
|
return this.dashboardService.getSummary(userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ import { DashboardController } from "./dashboard.controller";
|
|||||||
import { AdsModule } from "../ads/ads.module";
|
import { AdsModule } from "../ads/ads.module";
|
||||||
import { DanakServicesModule } from "../danak-services/danak-services.module";
|
import { DanakServicesModule } from "../danak-services/danak-services.module";
|
||||||
import { InvoicesModule } from "../invoices/invoices.module";
|
import { InvoicesModule } from "../invoices/invoices.module";
|
||||||
|
import { NotificationModule } from "../notifications/notifications.module";
|
||||||
import { TicketsModule } from "../tickets/tickets.module";
|
import { TicketsModule } from "../tickets/tickets.module";
|
||||||
import { UsersModule } from "../users/users.module";
|
import { UsersModule } from "../users/users.module";
|
||||||
import { DashboardService } from "./providers/dashboard.service";
|
import { DashboardService } from "./providers/dashboard.service";
|
||||||
import { SubscriptionsModule } from "../subscriptions/subscriptions.module";
|
import { SubscriptionsModule } from "../subscriptions/subscriptions.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [InvoicesModule, TicketsModule, UsersModule, AdsModule, DanakServicesModule, SubscriptionsModule],
|
imports: [InvoicesModule, TicketsModule, UsersModule, AdsModule, DanakServicesModule, SubscriptionsModule, NotificationModule],
|
||||||
providers: [DashboardService],
|
providers: [DashboardService],
|
||||||
controllers: [DashboardController],
|
controllers: [DashboardController],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { Injectable } from "@nestjs/common";
|
import { Injectable } from "@nestjs/common";
|
||||||
|
|
||||||
import { AdsService } from "../../ads/providers/ads.service";
|
import { AdsService } from "../../ads/providers/ads.service";
|
||||||
|
// import { AnnouncementService } from "../../announcements/providers/announcement.service";
|
||||||
import { DanakServicesService } from "../../danak-services/providers/danak-services.service";
|
import { DanakServicesService } from "../../danak-services/providers/danak-services.service";
|
||||||
import { InvoicesService } from "../../invoices/providers/invoices.service";
|
import { InvoicesService } from "../../invoices/providers/invoices.service";
|
||||||
|
import { NotificationsService } from "../../notifications/providers/notifications.service";
|
||||||
import { SubscriptionsService } from "../../subscriptions/providers/subscriptions.service";
|
import { SubscriptionsService } from "../../subscriptions/providers/subscriptions.service";
|
||||||
import { TicketsService } from "../../tickets/providers/tickets.service";
|
import { TicketsService } from "../../tickets/providers/tickets.service";
|
||||||
import { UsersService } from "../../users/providers/users.service";
|
import { UsersService } from "../../users/providers/users.service";
|
||||||
@@ -16,10 +18,27 @@ export class DashboardService {
|
|||||||
private readonly ticketsService: TicketsService,
|
private readonly ticketsService: TicketsService,
|
||||||
private readonly adsService: AdsService,
|
private readonly adsService: AdsService,
|
||||||
private readonly subscriptionsService: SubscriptionsService,
|
private readonly subscriptionsService: SubscriptionsService,
|
||||||
|
private readonly notificationsService: NotificationsService,
|
||||||
|
// private readonly announcementService: AnnouncementService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
//************************************ */
|
//************************************ */
|
||||||
|
|
||||||
|
async getSummary(userId: string) {
|
||||||
|
const subscriptionCount = await this.subscriptionsService.countUserSubscriptions(userId);
|
||||||
|
const ticketCount = await this.ticketsService.countUserTickets(userId);
|
||||||
|
const invoiceCount = await this.invoicesService.countUserInvoices(userId);
|
||||||
|
// const announcementCount = await this.announcementService.countUserAnnouncements(userId);
|
||||||
|
const notificationCount = await this.notificationsService.countUserNotifications(userId);
|
||||||
|
return {
|
||||||
|
subscriptionCount,
|
||||||
|
ticketCount,
|
||||||
|
invoiceCount,
|
||||||
|
announcementCount: 0,
|
||||||
|
notificationCount,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async reports() {
|
async reports() {
|
||||||
const danakServicesCount = await this.getDanakServicesCount();
|
const danakServicesCount = await this.getDanakServicesCount();
|
||||||
const customersCount = await this.getCustomersCount();
|
const customersCount = await this.getCustomersCount();
|
||||||
|
|||||||
@@ -417,6 +417,16 @@ export class InvoicesService {
|
|||||||
});
|
});
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
//*********************************** */
|
||||||
|
|
||||||
|
async countUserInvoices(userId: string) {
|
||||||
|
const invoiceCount = await this.invoiceRepository.count({
|
||||||
|
where: {
|
||||||
|
user: { id: userId },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return invoiceCount;
|
||||||
|
}
|
||||||
|
|
||||||
//*********************************** */
|
//*********************************** */
|
||||||
|
|
||||||
|
|||||||
@@ -99,8 +99,15 @@ export class NotificationsService {
|
|||||||
|
|
||||||
//************************ */
|
//************************ */
|
||||||
|
|
||||||
|
async countUserNotifications(userId: string) {
|
||||||
|
const notificationCount = await this.notificationRepository.count({ where: { recipient: { id: userId }, isRead: false } });
|
||||||
|
return notificationCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
//************************ */
|
||||||
|
|
||||||
async markAllAsRead(userId: string) {
|
async markAllAsRead(userId: string) {
|
||||||
await this.notificationRepository.update({ recipient: { id: userId } }, { isRead: true });
|
await this.notificationRepository.delete({ recipient: { id: userId } });
|
||||||
return {
|
return {
|
||||||
message: CommonMessage.UPDATE_SUCCESS,
|
message: CommonMessage.UPDATE_SUCCESS,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -284,6 +284,15 @@ export class SubscriptionsService {
|
|||||||
await queryRunner.release();
|
await queryRunner.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//************************************ */
|
||||||
|
|
||||||
|
async countUserSubscriptions(userId: string) {
|
||||||
|
const subscriptionCount = await this.userSubscriptionsRepository.count({
|
||||||
|
where: { user: { id: userId }, status: SubscriptionStatus.ACTIVE },
|
||||||
|
});
|
||||||
|
|
||||||
|
return subscriptionCount;
|
||||||
|
}
|
||||||
|
|
||||||
//************************************ */
|
//************************************ */
|
||||||
|
|
||||||
|
|||||||
@@ -318,26 +318,13 @@ export class TicketsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//******************************** */
|
//******************************** */
|
||||||
|
async countUserTickets(userId: string) {
|
||||||
|
const ticketCount = await this.ticketsRepository.count({
|
||||||
|
where: {
|
||||||
|
user: { id: userId },
|
||||||
|
status: Not(TicketStatus.CLOSED),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return ticketCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// async getTickets(queryDto: SearchTicketQueryDto, userId: string) {
|
|
||||||
// const { limit, skip } = PaginationUtils(queryDto);
|
|
||||||
// //TODO:add danak-service to query
|
|
||||||
// const queryBuilder = this.ticketsRepository
|
|
||||||
// .createQueryBuilder("ticket")
|
|
||||||
// .leftJoinAndSelect("ticket.category", "category")
|
|
||||||
// .leftJoinAndSelect("ticket.user", "user")
|
|
||||||
// .where("user.id = :userId", { userId })
|
|
||||||
// .orderBy("ticket.createdAt", "DESC");
|
|
||||||
|
|
||||||
// if (queryDto.status) {
|
|
||||||
// queryBuilder.andWhere("ticket.status = :status", { status: queryDto.status });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const [tickets, count] = await queryBuilder.skip(skip).take(limit).getManyAndCount();
|
|
||||||
|
|
||||||
// return {
|
|
||||||
// tickets,
|
|
||||||
// count,
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export class CreateCustomerDto {
|
|||||||
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
|
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
|
||||||
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
|
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
|
||||||
@Length(11, 11, { message: AuthMessage.PHONE_SHOULD_BE_11_DIGIT })
|
@Length(11, 11, { message: AuthMessage.PHONE_SHOULD_BE_11_DIGIT })
|
||||||
@ApiProperty({ description: "phone number", default: "09123456789" })
|
@ApiProperty({ description: "phone number", default: "09922320740" })
|
||||||
phone: string;
|
phone: string;
|
||||||
|
|
||||||
@IsNotEmpty({ message: AuthMessage.FIRST_NAME_NOT_EMPTY })
|
@IsNotEmpty({ message: AuthMessage.FIRST_NAME_NOT_EMPTY })
|
||||||
|
|||||||
@@ -26,75 +26,52 @@ import { VerifyOtpDto } from "../auth/DTO/verify-otp.dto";
|
|||||||
|
|
||||||
@Controller("users")
|
@Controller("users")
|
||||||
@ApiTags("users")
|
@ApiTags("users")
|
||||||
|
@AuthGuards()
|
||||||
export class UsersController {
|
export class UsersController {
|
||||||
constructor(private usersService: UsersService) {}
|
constructor(private usersService: UsersService) {}
|
||||||
|
|
||||||
/************************************************************ */
|
//
|
||||||
|
|
||||||
@AuthGuards()
|
|
||||||
@ApiOperation({ summary: "Get user profile" })
|
@ApiOperation({ summary: "Get user profile" })
|
||||||
@Get("me")
|
@Get("me")
|
||||||
getMe(@UserDec("id") userId: string) {
|
getMe(@UserDec("id") userId: string) {
|
||||||
return this.usersService.getMe(userId);
|
return this.usersService.getMe(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
//
|
||||||
|
|
||||||
@AuthGuards()
|
|
||||||
@ApiOperation({ summary: "Get user financial info" })
|
@ApiOperation({ summary: "Get user financial info" })
|
||||||
@Get("me/financial-info")
|
@Get("me/financial-info")
|
||||||
getFinancialInfo(@UserDec("id") userId: string) {
|
getFinancialInfo(@UserDec("id") userId: string) {
|
||||||
return this.usersService.getMyFinancialInfo(userId);
|
return this.usersService.getMyFinancialInfo(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@AuthGuards()
|
|
||||||
@ApiOperation({ summary: "Update user profile" })
|
@ApiOperation({ summary: "Update user profile" })
|
||||||
@Patch("update-profile")
|
@Patch("update-profile")
|
||||||
updateProfile(@Body() updateProfileDto: UpdateProfileDto, @UserDec("id") userId: string) {
|
updateProfile(@Body() updateProfileDto: UpdateProfileDto, @UserDec("id") userId: string) {
|
||||||
return this.usersService.updateProfile(userId, updateProfileDto);
|
return this.usersService.updateProfile(userId, updateProfileDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@AuthGuards()
|
|
||||||
@ApiOperation({ summary: "change user email" })
|
@ApiOperation({ summary: "change user email" })
|
||||||
@Patch("change-email")
|
@Patch("change-email")
|
||||||
changeEmail(@Body() changeEmailDto: ChangeEmailDto, @UserDec("id") userId: string) {
|
changeEmail(@Body() changeEmailDto: ChangeEmailDto, @UserDec("id") userId: string) {
|
||||||
return this.usersService.changeEmail(userId, changeEmailDto);
|
return this.usersService.changeEmail(userId, changeEmailDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@ApiOperation({ summary: "Verify email" })
|
@ApiOperation({ summary: "Verify email" })
|
||||||
@Get("verify-email")
|
@Get("verify-email")
|
||||||
verifyEmail(@Query() queryDto: EmailVerifyQueryDto, @Res({ passthrough: true }) rep: FastifyReply) {
|
verifyEmail(@Query() queryDto: EmailVerifyQueryDto, @Res({ passthrough: true }) rep: FastifyReply) {
|
||||||
return this.usersService.verifyEmail(queryDto, rep);
|
return this.usersService.verifyEmail(queryDto, rep);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@AuthGuards()
|
|
||||||
@ApiOperation({ summary: "change user phone" })
|
@ApiOperation({ summary: "change user phone" })
|
||||||
@Patch("change-phone")
|
@Patch("change-phone")
|
||||||
changePhone(@Body() changeDto: RequestOtpDto, @UserDec("id") userId: string) {
|
changePhone(@Body() changeDto: RequestOtpDto, @UserDec("id") userId: string) {
|
||||||
return this.usersService.changePhone(userId, changeDto);
|
return this.usersService.changePhone(userId, changeDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@AuthGuards()
|
|
||||||
@ApiOperation({ summary: "Verify phone" })
|
@ApiOperation({ summary: "Verify phone" })
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@Patch("verify-phone")
|
@Patch("verify-phone")
|
||||||
verifyPhone(@Body() verifyOtpDto: VerifyOtpDto, @UserDec("id") userId: string) {
|
verifyPhone(@Body() verifyOtpDto: VerifyOtpDto, @UserDec("id") userId: string) {
|
||||||
return this.usersService.verifyPhone(verifyOtpDto, userId);
|
return this.usersService.verifyPhone(verifyOtpDto, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@AuthGuards()
|
|
||||||
@ApiOperation({ summary: "Check validity of user field" })
|
@ApiOperation({ summary: "Check validity of user field" })
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@Post("check-validity")
|
@Post("check-validity")
|
||||||
@@ -102,9 +79,6 @@ export class UsersController {
|
|||||||
return this.usersService.checkValidity(checkValidityDto, userId);
|
return this.usersService.checkValidity(checkValidityDto, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@AuthGuards()
|
|
||||||
@ApiOperation({ summary: "Create user group ==> admin route" })
|
@ApiOperation({ summary: "Create user group ==> admin route" })
|
||||||
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
||||||
@Post("user-group")
|
@Post("user-group")
|
||||||
@@ -112,98 +86,68 @@ export class UsersController {
|
|||||||
return this.usersService.createUserGroup(createDto);
|
return this.usersService.createUserGroup(createDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@ApiOperation({ summary: "get all user group ==> admin route" })
|
@ApiOperation({ summary: "get all user group ==> admin route" })
|
||||||
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
||||||
@AuthGuards()
|
|
||||||
@Get("user-group")
|
@Get("user-group")
|
||||||
UserGroups() {
|
UserGroups() {
|
||||||
return this.usersService.getUserGroups();
|
return this.usersService.getUserGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@ApiOperation({ summary: "get all users ==> admin route" })
|
@ApiOperation({ summary: "get all users ==> admin route" })
|
||||||
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
||||||
@AuthGuards()
|
|
||||||
@Get()
|
@Get()
|
||||||
Users() {
|
Users() {
|
||||||
return this.usersService.findAllUsers();
|
return this.usersService.findAllUsers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@ApiOperation({ summary: "get all customers ==> admin route" })
|
@ApiOperation({ summary: "get all customers ==> admin route" })
|
||||||
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
||||||
@AuthGuards()
|
|
||||||
@Get("customers")
|
@Get("customers")
|
||||||
customers(@Query() queryDto: SearchCustomersDto) {
|
customers(@Query() queryDto: SearchCustomersDto) {
|
||||||
return this.usersService.findAllCustomers(queryDto);
|
return this.usersService.findAllCustomers(queryDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@ApiOperation({ summary: "get all customers ==> admin route" })
|
@ApiOperation({ summary: "get all customers ==> admin route" })
|
||||||
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
||||||
@AuthGuards()
|
|
||||||
@Get("customers/:id")
|
@Get("customers/:id")
|
||||||
customer(@Param() paramDto: ParamDto) {
|
customer(@Param() paramDto: ParamDto) {
|
||||||
return this.usersService.findOneCustomer(paramDto.id);
|
return this.usersService.findOneCustomer(paramDto.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@ApiOperation({ summary: "get all admins ==> admin route" })
|
@ApiOperation({ summary: "get all admins ==> admin route" })
|
||||||
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
||||||
@AuthGuards()
|
|
||||||
@Get("admins")
|
@Get("admins")
|
||||||
getAdmins(@Query() queryDto: SearchAdminQueryDto) {
|
getAdmins(@Query() queryDto: SearchAdminQueryDto) {
|
||||||
return this.usersService.getAdmins(queryDto);
|
return this.usersService.getAdmins(queryDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@ApiOperation({ summary: "create admin ==> admin route" })
|
@ApiOperation({ summary: "create admin ==> admin route" })
|
||||||
@AuthGuards()
|
|
||||||
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
||||||
@Post("admins")
|
@Post("admins")
|
||||||
createAdmin(@Body() createDto: CreateAdminDto) {
|
createAdmin(@Body() createDto: CreateAdminDto) {
|
||||||
return this.usersService.createAdmin(createDto);
|
return this.usersService.createAdmin(createDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@ApiOperation({ summary: "get all permissions ==> admin route" })
|
@ApiOperation({ summary: "get all permissions ==> admin route" })
|
||||||
@AuthGuards()
|
|
||||||
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
||||||
@Get("permissions")
|
@Get("permissions")
|
||||||
getPermissions() {
|
getPermissions() {
|
||||||
return this.usersService.getPermissions();
|
return this.usersService.getPermissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@ApiOperation({ summary: "get all roles ==> admin route" })
|
@ApiOperation({ summary: "get all roles ==> admin route" })
|
||||||
@AuthGuards()
|
|
||||||
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
||||||
@Get("roles")
|
@Get("roles")
|
||||||
getRoles(@Query() queryDto: SearchRolesQueryDto) {
|
getRoles(@Query() queryDto: SearchRolesQueryDto) {
|
||||||
return this.usersService.getRoles(queryDto);
|
return this.usersService.getRoles(queryDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@ApiOperation({ summary: "create role ==> admin route" })
|
@ApiOperation({ summary: "create role ==> admin route" })
|
||||||
@AuthGuards()
|
|
||||||
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
|
||||||
@Post("roles")
|
@Post("roles")
|
||||||
createRole(@Body() createDto: CreateRoleDto) {
|
createRole(@Body() createDto: CreateRoleDto) {
|
||||||
return this.usersService.createRole(createDto);
|
return this.usersService.createRole(createDto);
|
||||||
}
|
}
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@AuthGuards()
|
|
||||||
@ApiOperation({ summary: "Create real user data" })
|
@ApiOperation({ summary: "Create real user data" })
|
||||||
@HttpCode(HttpStatus.CREATED)
|
@HttpCode(HttpStatus.CREATED)
|
||||||
@Post("real-user")
|
@Post("real-user")
|
||||||
@@ -211,9 +155,6 @@ export class UsersController {
|
|||||||
return this.usersService.createRealUserData(createDto, userId);
|
return this.usersService.createRealUserData(createDto, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@AuthGuards()
|
|
||||||
@ApiOperation({ summary: "Create legal user data" })
|
@ApiOperation({ summary: "Create legal user data" })
|
||||||
@HttpCode(HttpStatus.CREATED)
|
@HttpCode(HttpStatus.CREATED)
|
||||||
@Post("legal-user")
|
@Post("legal-user")
|
||||||
@@ -221,15 +162,10 @@ export class UsersController {
|
|||||||
return this.usersService.createLegalUserData(createDto, userId);
|
return this.usersService.createLegalUserData(createDto, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
|
|
||||||
@AuthGuards()
|
|
||||||
@ApiOperation({ summary: "Create customer" })
|
@ApiOperation({ summary: "Create customer" })
|
||||||
@HttpCode(HttpStatus.CREATED)
|
@HttpCode(HttpStatus.CREATED)
|
||||||
@Post("customer")
|
@Post("customer")
|
||||||
createCustomer(@Body() createDto: CreateCustomerDto) {
|
createCustomer(@Body() createDto: CreateCustomerDto) {
|
||||||
return this.usersService.createCustomer(createDto);
|
return this.usersService.createCustomer(createDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************ */
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { BadRequestException, Injectable } from "@nestjs/common";
|
import { BadRequestException, Injectable } from "@nestjs/common";
|
||||||
// eslint-disable-next-line import/no-named-as-default
|
// eslint-disable-next-line import/no-named-as-default
|
||||||
import dayjs from "dayjs";
|
|
||||||
import Decimal from "decimal.js";
|
import Decimal from "decimal.js";
|
||||||
import { QueryRunner } from "typeorm";
|
import { QueryRunner } from "typeorm";
|
||||||
|
|
||||||
@@ -116,75 +115,29 @@ export class WalletsService {
|
|||||||
.take(limit)
|
.take(limit)
|
||||||
.getManyAndCount();
|
.getManyAndCount();
|
||||||
|
|
||||||
// Current month totals
|
|
||||||
const totals = await this.walletsTransactionRepo
|
const totals = await this.walletsTransactionRepo
|
||||||
.createQueryBuilder("transaction")
|
.createQueryBuilder("transaction")
|
||||||
.leftJoin("transaction.wallet", "wallet")
|
.leftJoin("transaction.wallet", "wallet")
|
||||||
.where("wallet.userId = :userId", { userId })
|
.where("wallet.userId = :userId", { userId })
|
||||||
.select([
|
.select([
|
||||||
`COALESCE(SUM(CASE WHEN transaction.type = '${TransactionType.DEPOSIT}' THEN transaction.amount ELSE 0 END), 0) AS "totalDeposits"`,
|
`COALESCE(SUM(CASE WHEN transaction.type = '${TransactionType.DEPOSIT}' THEN transaction.amount ELSE 0 END), 0) AS "totalDeposits"`,
|
||||||
`COALESCE(SUM(CASE WHEN transaction.type = '${TransactionType.WITHDRAWAL}' THEN transaction.amount ELSE 0 END), 0) AS "totalWithdrawals"`,
|
`COALESCE(SUM(CASE WHEN transaction.type = '${TransactionType.DEBIT}' THEN transaction.amount ELSE 0 END), 0) AS "totalWithdrawals"`,
|
||||||
])
|
|
||||||
.getRawOne();
|
|
||||||
|
|
||||||
const now = dayjs();
|
|
||||||
const firstDayOfMonth = now.startOf("month").toDate();
|
|
||||||
const firstDayOfPrevMonth = now.subtract(1, "month").startOf("month").toDate();
|
|
||||||
const lastDayOfPrevMonth = now.subtract(1, "month").endOf("month").toDate();
|
|
||||||
|
|
||||||
const prevMonthTotals = await this.walletsTransactionRepo
|
|
||||||
.createQueryBuilder("transaction")
|
|
||||||
.leftJoin("transaction.wallet", "wallet")
|
|
||||||
.where("wallet.userId = :userId", { userId })
|
|
||||||
.andWhere("transaction.createdAt >= :startDate", { startDate: firstDayOfPrevMonth })
|
|
||||||
.andWhere("transaction.createdAt <= :endDate", { endDate: lastDayOfPrevMonth })
|
|
||||||
.select([
|
|
||||||
`COALESCE(SUM(CASE WHEN transaction.type = '${TransactionType.DEPOSIT}' THEN transaction.amount ELSE 0 END), 0) AS "totalDeposits"`,
|
|
||||||
`COALESCE(SUM(CASE WHEN transaction.type = '${TransactionType.WITHDRAWAL}' THEN transaction.amount ELSE 0 END), 0) AS "totalWithdrawals"`,
|
|
||||||
])
|
])
|
||||||
.getRawOne();
|
.getRawOne();
|
||||||
|
|
||||||
const wallet = await this.walletsRepository.findOneBy({ user: { id: userId } });
|
const wallet = await this.walletsRepository.findOneBy({ user: { id: userId } });
|
||||||
if (!wallet) throw new BadRequestException(WalletMessage.WALLET_NOT_FOUND);
|
if (!wallet) throw new BadRequestException(WalletMessage.WALLET_NOT_FOUND);
|
||||||
|
|
||||||
const prevMonthWallet = await this.walletsTransactionRepo
|
|
||||||
.createQueryBuilder("transaction")
|
|
||||||
.leftJoin("transaction.wallet", "wallet")
|
|
||||||
.where("wallet.userId = :userId", { userId })
|
|
||||||
.andWhere("transaction.createdAt < :date", { date: firstDayOfMonth })
|
|
||||||
.select([
|
|
||||||
`COALESCE(SUM(CASE WHEN transaction.type = '${TransactionType.DEPOSIT}' THEN transaction.amount ELSE 0 END), 0) -
|
|
||||||
COALESCE(SUM(CASE WHEN transaction.type = '${TransactionType.WITHDRAWAL}' THEN transaction.amount ELSE 0 END), 0) AS "prevBalance"`,
|
|
||||||
])
|
|
||||||
.getRawOne();
|
|
||||||
|
|
||||||
//TODO:fix this
|
|
||||||
const currentDeposits = new Decimal(decimal(totals.totalDeposits) || 0);
|
|
||||||
const prevDeposits = new Decimal(decimal(prevMonthTotals.totalDeposits) || 0);
|
|
||||||
const depositsPercentChange = prevDeposits.isZero() ? null : currentDeposits.minus(prevDeposits).div(prevDeposits).mul(100);
|
|
||||||
|
|
||||||
const currentWithdrawals = new Decimal(decimal(totals.totalWithdrawals) || 0);
|
|
||||||
const prevWithdrawals = new Decimal(decimal(prevMonthTotals.totalWithdrawals) || 0);
|
|
||||||
const withdrawalsPercentChange = prevWithdrawals.isZero()
|
|
||||||
? null
|
|
||||||
: currentWithdrawals.minus(prevWithdrawals).div(prevWithdrawals).mul(100);
|
|
||||||
|
|
||||||
const currentBalance = wallet.balance;
|
|
||||||
const prevBalance = decimal(prevMonthWallet.prevBalance) || new Decimal(0);
|
|
||||||
const prevBalanceDecimal = new Decimal(prevBalance);
|
|
||||||
const balancePercentChange = prevBalanceDecimal.isZero()
|
|
||||||
? null
|
|
||||||
: currentBalance.minus(prevBalanceDecimal).div(prevBalanceDecimal).mul(100).toNumber();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
balance: currentBalance,
|
balance: wallet.balance,
|
||||||
balancePercentChange,
|
|
||||||
transactions,
|
transactions,
|
||||||
count,
|
count,
|
||||||
totalDeposits: currentDeposits.toNumber(),
|
totalDeposits: decimal(totals.totalDeposits) || 0,
|
||||||
totalDepositsPercentChange: depositsPercentChange,
|
totalWithdrawals: decimal(totals.totalWithdrawals) || 0,
|
||||||
totalWithdrawals: currentWithdrawals.toNumber(),
|
//TODO:fix this
|
||||||
totalWithdrawalsPercentChange: withdrawalsPercentChange,
|
balancePercentChange: 5,
|
||||||
|
totalDepositsPercentChange: 4,
|
||||||
|
totalWithdrawalsPercentChange: 10,
|
||||||
paginate: true,
|
paginate: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user