end points to get current points and wallet

This commit is contained in:
2025-12-29 22:14:02 +03:30
parent 85067f0373
commit e067912bb4
6 changed files with 54 additions and 29 deletions
+1 -1
View File
@@ -7,7 +7,7 @@
"source.fixAll.eslint": "explicit" "source.fixAll.eslint": "explicit"
}, },
"[typescript]": { "[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features" "editor.defaultFormatter": "esbenp.prettier-vscode"
}, },
"[json]": { "[json]": {
"editor.defaultFormatter": "vscode.json-language-features" "editor.defaultFormatter": "vscode.json-language-features"
@@ -14,11 +14,15 @@ import { API_HEADER_SLUG } from 'src/common/constants/index';
import { UserSuccessMessage } from 'src/common/enums/message.enum'; import { UserSuccessMessage } from 'src/common/enums/message.enum';
import { Permissions } from 'src/common/decorators/permissions.decorator'; import { Permissions } from 'src/common/decorators/permissions.decorator';
import { Permission } from 'src/common/enums/permission.enum'; import { Permission } from 'src/common/enums/permission.enum';
import { WalletService } from '../providers/wallet.service';
@ApiTags('User') @ApiTags('User')
@Controller() @Controller()
export class UsersController { export class UsersController {
constructor(private readonly userService: UserService) { } constructor(
private readonly userService: UserService,
private readonly walletService: WalletService,
) {}
@UseGuards(AuthGuard) @UseGuards(AuthGuard)
@ApiBearerAuth() @ApiBearerAuth()
@@ -55,9 +59,19 @@ export class UsersController {
@ApiBearerAuth() @ApiBearerAuth()
@ApiOperation({ summary: 'Get User Wallet' }) @ApiOperation({ summary: 'Get User Wallet' })
@ApiHeader(API_HEADER_SLUG) @ApiHeader(API_HEADER_SLUG)
@Get('public/user/wallet') @Get('public/user/wallet/balance')
async getUserWalletBalance(@UserId() userId: string, @RestId() restId: string) {
const wallet = await this.walletService.getUserCurrentWalletBalance(userId, restId);
return wallet;
}
@UseGuards(AuthGuard)
@ApiBearerAuth()
@ApiOperation({ summary: 'Get User Wallet' })
@ApiHeader(API_HEADER_SLUG)
@Get('public/user/points/balance')
async getUserWallet(@UserId() userId: string, @RestId() restId: string) { async getUserWallet(@UserId() userId: string, @RestId() restId: string) {
const wallet = await this.userService.getUserWallet(userId, restId); const wallet = await this.walletService.getUserCurrentPoinrBalance(userId, restId);
return wallet; return wallet;
} }
@@ -166,6 +180,4 @@ export class UsersController {
) { ) {
return this.userService.findAll(restId, query); return this.userService.findAll(restId, query);
} }
} }
@@ -1,11 +1,11 @@
import { Entity, Property, ManyToOne, Index, Unique, Enum } from '@mikro-orm/core'; import { Entity, Property, ManyToOne, Index, Enum } from '@mikro-orm/core';
import { BaseEntity } from '../../../common/entities/base.entity'; import { BaseEntity } from '../../../common/entities/base.entity';
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity'; import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
import { User } from './user.entity'; import { User } from './user.entity';
import { PointTransactionReason } from '../interface/point'; import { PointTransactionReason } from '../interface/point';
import { PointTransactionType } from '../interface/point'; import { PointTransactionType } from '../interface/point';
@Entity({ tableName: 'user_wallets' }) @Entity({ tableName: 'point_transactions' })
@Index({ properties: ['user', 'restaurant'] }) // Composite index for most common query: find wallet by user and restaurant @Index({ properties: ['user', 'restaurant'] }) // Composite index for most common query: find wallet by user and restaurant
@Index({ properties: ['user'] }) // Index for queries finding all wallets for a user @Index({ properties: ['user'] }) // Index for queries finding all wallets for a user
@Index({ properties: ['restaurant'] }) // Index for queries finding all wallets for a restaurant @Index({ properties: ['restaurant'] }) // Index for queries finding all wallets for a restaurant
+17 -7
View File
@@ -7,12 +7,13 @@ import { FindWalletTransactionsDto } from '../dto/find-wallet-transactions.dto';
import { CreateWalletTransactionDto } from '../dto/create-wallet-transaction.dto'; import { CreateWalletTransactionDto } from '../dto/create-wallet-transaction.dto';
import { PaginatedResult } from 'src/common/interfaces/pagination.interface'; import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
import { WalletTransactionType } from '../interface/wallet'; import { WalletTransactionType } from '../interface/wallet';
import { PointTransactionRepository } from '../repositories/point-transaction.repository';
@Injectable() @Injectable()
export class WalletService { export class WalletService {
constructor( constructor(
private readonly walletTransactionRepository: WalletTransactionRepository, private readonly walletTransactionRepository: WalletTransactionRepository,
private readonly em: EntityManager, private readonly pointTransactionRepository: PointTransactionRepository,
) { } ) { }
async getUserWalletTransactions( async getUserWalletTransactions(
@@ -107,9 +108,13 @@ export class WalletService {
} }
getUserWallet(userId: string, restId: string): Promise<WalletTransaction | null> { getUserWallet(userId: string, restId: string): Promise<WalletTransaction | null> {
return this.walletTransactionRepository.findOne({ user: { id: userId }, return this.walletTransactionRepository.findOne(
restaurant: { id: restId } }, {
{ orderBy: { createdAt: 'DESC' } }); user: { id: userId },
restaurant: { id: restId },
},
{ orderBy: { createdAt: 'DESC' } },
);
} }
async createTransaction( async createTransaction(
@@ -143,9 +148,7 @@ export class WalletService {
newBalance = currentBalance + amount; newBalance = currentBalance + amount;
} else if (type === WalletTransactionType.DEBIT) { } else if (type === WalletTransactionType.DEBIT) {
if (currentBalance < amount) { if (currentBalance < amount) {
throw new BadRequestException( throw new BadRequestException(`Insufficient wallet balance. Current: ${currentBalance}, Required: ${amount}.`);
`Insufficient wallet balance. Current: ${currentBalance}, Required: ${amount}.`,
);
} }
newBalance = currentBalance - amount; newBalance = currentBalance - amount;
} else { } else {
@@ -168,4 +171,11 @@ export class WalletService {
await em.persistAndFlush([walletTransaction, transaction]); await em.persistAndFlush([walletTransaction, transaction]);
return transaction; return transaction;
} }
getUserCurrentWalletBalance(userId: string, restuarantId: string) {
return this.walletTransactionRepository.getCurrentWalletBalance(userId, restuarantId)
}
getUserCurrentPoinrBalance(userId: string, restuarantId: string) {
return this.pointTransactionRepository.getcurrentPointBalance(userId, restuarantId)
}
} }
@@ -8,10 +8,14 @@ export class WalletTransactionRepository extends EntityRepository<WalletTransact
super(em, WalletTransaction); super(em, WalletTransaction);
} }
async getCurrentWalletBalance(userId: string, restaurantId: string): Promise<number> { async getCurrentWalletBalance(userId: string, restaurantId: string): Promise<number> {
const walletTransaction = await this.em.findOne(WalletTransaction, { const walletTransaction = await this.em.findOne(
WalletTransaction,
{
user: { id: userId }, user: { id: userId },
restaurant: { id: restaurantId }, restaurant: { id: restaurantId },
}, { orderBy: { createdAt: 'desc' } }); },
{ orderBy: { createdAt: 'desc' } },
);
return walletTransaction?.balance || 0; return walletTransaction?.balance || 0;
} }
} }
+8 -9
View File
@@ -11,17 +11,16 @@ import { WalletTransactionRepository } from './repositories/wallet-transaction.r
import { WalletService } from './providers/wallet.service'; import { WalletService } from './providers/wallet.service';
import { WalletTransaction } from './entities/wallet-transaction.entity'; import { WalletTransaction } from './entities/wallet-transaction.entity';
import { PointTransaction } from './entities/point-transaction.entity'; import { PointTransaction } from './entities/point-transaction.entity';
import { PointTransactionRepository } from './repositories/point-transaction.repository';
@Module({ @Module({
providers: [UserService, WalletService, UserRepository, WalletTransactionRepository], providers: [UserService, WalletService, UserRepository, WalletTransactionRepository, PointTransactionRepository],
controllers: [UsersController], controllers: [UsersController],
imports: [MikroOrmModule.forFeature([ imports: [
User, MikroOrmModule.forFeature([User, UserAddress, WalletTransaction, PointTransaction]),
UserAddress, JwtModule,
WalletTransaction, RestaurantsModule,
PointTransaction ],
]), exports: [UserService, WalletService, UserRepository, WalletTransactionRepository, PointTransactionRepository],
JwtModule, RestaurantsModule],
exports: [UserService, WalletService, UserRepository, WalletTransactionRepository],
}) })
export class UserModule {} export class UserModule {}