wallet transaction entity added
This commit is contained in:
@@ -169,140 +169,4 @@ export class OrderListeners {
|
||||
}
|
||||
}
|
||||
|
||||
// private factory(orderStatus: OrderStatus, event: OrderStatusChangedEvent) {
|
||||
// switch (orderStatus) {
|
||||
// case OrderStatus.CONFIRMED:
|
||||
// return {
|
||||
// message: {
|
||||
// title: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// content: `Order ${event.orderNumber} confirmed .`,
|
||||
// sms: {
|
||||
// templateId: this.orderCreatedSmsTemplateId,
|
||||
// parameters: {
|
||||
// orderNumber: event.orderNumber,
|
||||
// },
|
||||
// },
|
||||
// pushNotif: {
|
||||
// title: `تایید سفارش`,
|
||||
// content: `سفارش شماره ${event.orderNumber} با موفقیت تایید شد`,
|
||||
// icon: `Order ${event.orderNumber} has been confirmed successfully`,
|
||||
// action: {
|
||||
// type: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// url: ``,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// case OrderStatus.PREPARING:
|
||||
// return {
|
||||
// message: {
|
||||
// title: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// content: `سفارش شماره ${event.orderNumber} در حال آمادهسازی است`,
|
||||
// sms: {
|
||||
// templateId: this.orderCreatedSmsTemplateId,
|
||||
// parameters: {
|
||||
// orderNumber: event.orderNumber,
|
||||
// },
|
||||
// },
|
||||
// pushNotif: {
|
||||
// title: `آمادهسازی سفارش`,
|
||||
// content: `سفارش شماره ${event.orderNumber} در حال آمادهسازی است`,
|
||||
// icon: `Order ${event.orderNumber} is preparing`,
|
||||
// action: {
|
||||
// type: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// url: ``,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// case OrderStatus.DELIVERED_TO_RECEPTIONIST:
|
||||
// return {
|
||||
// message: {
|
||||
// title: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// content: `سفارش شماره ${event.orderNumber} آماده است`,
|
||||
// sms: {
|
||||
// templateId: this.orderCreatedSmsTemplateId,
|
||||
// parameters: {
|
||||
// orderNumber: event.orderNumber,
|
||||
// },
|
||||
// },
|
||||
// pushNotif: {
|
||||
// title: `سفارش آماده است`,
|
||||
// content: `سفارش شماره ${event.orderNumber} آماده است`,
|
||||
// icon: `Order ${event.orderNumber} is ready`,
|
||||
// action: {
|
||||
// type: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// url: ``,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// case OrderStatus.SHIPPED:
|
||||
// return {
|
||||
// message: {
|
||||
// title: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// content: `سفارش شماره ${event.orderNumber} ارسال شد`,
|
||||
// sms: {
|
||||
// templateId: this.orderCreatedSmsTemplateId,
|
||||
// parameters: {
|
||||
// orderNumber: event.orderNumber,
|
||||
// },
|
||||
// },
|
||||
// pushNotif: {
|
||||
// title: `ارسال سفارش`,
|
||||
// content: `سفارش شماره ${event.orderNumber} ارسال شد`,
|
||||
// icon: `Order ${event.orderNumber} is shipped`,
|
||||
// action: {
|
||||
// type: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// url: ``,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// case OrderStatus.CANCELED:
|
||||
// return {
|
||||
// message: {
|
||||
// title: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// content: `سفارش شماره ${event.orderNumber} لغو شد`,
|
||||
// sms: {
|
||||
// templateId: this.orderCreatedSmsTemplateId,
|
||||
// parameters: {
|
||||
// orderNumber: event.orderNumber,
|
||||
// },
|
||||
// },
|
||||
// pushNotif: {
|
||||
// title: `لغو سفارش`,
|
||||
// content: `سفارش شماره ${event.orderNumber} لغو شد`,
|
||||
// icon: `Order ${event.orderNumber} is canceled`,
|
||||
// action: {
|
||||
// type: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// url: ``,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// default:
|
||||
// return {
|
||||
// message: {
|
||||
// title: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// content: `Order ${event.orderNumber} is ....`,
|
||||
// sms: {
|
||||
// templateId: this.orderCreatedSmsTemplateId,
|
||||
// parameters: {
|
||||
// orderNumber: event.orderNumber,
|
||||
// },
|
||||
// },
|
||||
// pushNotif: {
|
||||
// title: `Order ${event.orderNumber} is ...`,
|
||||
// content: `Order ${event.orderNumber} is ...`,
|
||||
// icon: `Order ${event.orderNumber} is ...`,
|
||||
// action: {
|
||||
// type: NotifTitleEnum.ORDER_STATUS_CHANGED,
|
||||
// url: ``,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { UpdateUserAddressDto } from '../dto/update-user-address.dto';
|
||||
import { UserId } from 'src/common/decorators/user-id.decorator';
|
||||
import { RestId } from 'src/common/decorators';
|
||||
import { FindUsersDto } from '../dto/find-user.dto';
|
||||
import { FindWalletTransactionsDto } from '../dto/find-wallet-transactions.dto';
|
||||
import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard';
|
||||
import { API_HEADER_SLUG } from 'src/common/constants/index';
|
||||
import { UserSuccessMessage } from 'src/common/enums/message.enum';
|
||||
@@ -60,6 +61,21 @@ export class UsersController {
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Get User Wallet Transactions' })
|
||||
@ApiHeader(API_HEADER_SLUG)
|
||||
@Get('public/user/wallet/transactions')
|
||||
async getUserWalletTransactions(
|
||||
@UserId() userId: string,
|
||||
@RestId() restId: string,
|
||||
@Query(new ValidationPipe({ transform: true, whitelist: true }))
|
||||
query: FindWalletTransactionsDto,
|
||||
) {
|
||||
const transactions = await this.userService.getUserWalletTransactions(userId, restId, query);
|
||||
return transactions;
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Create a new address for the authenticated user' })
|
||||
@@ -142,7 +158,7 @@ export class UsersController {
|
||||
@ApiBearerAuth()
|
||||
@Permissions(Permission.MANAGE_USERS)
|
||||
@ApiOperation({ summary: 'Get paginated list of restuarant users with filters' })
|
||||
@Get('admin/users')
|
||||
@Get('admin/users')
|
||||
async findAllRestaurantUsers(
|
||||
@Query(new ValidationPipe({ transform: true, whitelist: true }))
|
||||
query: FindUsersDto,
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { IsNotEmpty, IsNumber, IsIn } from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { WalletTransactionType, WalletTransactionReason } from '../interface/wallet';
|
||||
|
||||
export class CreateWalletTransactionDto {
|
||||
@ApiProperty({
|
||||
description: 'Transaction amount',
|
||||
type: Number,
|
||||
example: 1000,
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsNumber()
|
||||
@Type(() => Number)
|
||||
amount!: number;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Transaction type',
|
||||
enum: WalletTransactionType,
|
||||
example: WalletTransactionType.CREDIT,
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsIn(Object.values(WalletTransactionType))
|
||||
type!: WalletTransactionType;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Transaction reason',
|
||||
enum: WalletTransactionReason,
|
||||
example: WalletTransactionReason.ORDER_PAYMENT,
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsIn(Object.values(WalletTransactionReason))
|
||||
reason!: WalletTransactionReason;
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import { IsOptional, IsString, IsNumber, Min, IsIn, IsDateString } from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { WalletTransactionType, WalletTransactionReason } from '../interface/wallet';
|
||||
|
||||
// Define the valid sort directions
|
||||
const sortOrderOptions = ['asc', 'desc'] as const;
|
||||
type SortOrder = (typeof sortOrderOptions)[number];
|
||||
|
||||
export class FindWalletTransactionsDto {
|
||||
/**
|
||||
* The page number to retrieve.
|
||||
* @default 1
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Page number',
|
||||
type: Number,
|
||||
default: 1,
|
||||
minimum: 1,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@Min(1)
|
||||
@Type(() => Number)
|
||||
page?: number = 1;
|
||||
|
||||
/**
|
||||
* The number of items per page.
|
||||
* @default 10
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Items per page',
|
||||
type: Number,
|
||||
default: 10,
|
||||
minimum: 1,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@Min(1)
|
||||
@Type(() => Number)
|
||||
limit?: number = 10;
|
||||
|
||||
/**
|
||||
* Filter by transaction type
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Transaction type filter',
|
||||
enum: WalletTransactionType,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsIn(Object.values(WalletTransactionType))
|
||||
type?: WalletTransactionType;
|
||||
|
||||
/**
|
||||
* Filter by transaction reason
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Transaction reason filter',
|
||||
enum: WalletTransactionReason,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsIn(Object.values(WalletTransactionReason))
|
||||
reason?: WalletTransactionReason;
|
||||
|
||||
/**
|
||||
* Filter transactions from this date onwards
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Start date filter (ISO 8601 format)',
|
||||
type: String,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
startDate?: string;
|
||||
|
||||
/**
|
||||
* Filter transactions up to this date
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'End date filter (ISO 8601 format)',
|
||||
type: String,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
endDate?: string;
|
||||
|
||||
/**
|
||||
* Minimum amount filter
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Minimum amount filter',
|
||||
type: Number,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@Type(() => Number)
|
||||
minAmount?: number;
|
||||
|
||||
/**
|
||||
* Maximum amount filter
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Maximum amount filter',
|
||||
type: Number,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@Type(() => Number)
|
||||
maxAmount?: number;
|
||||
|
||||
/**
|
||||
* The field to sort the results by.
|
||||
* @default "createdAt"
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Sort field',
|
||||
type: String,
|
||||
default: 'createdAt',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
orderBy?: string = 'createdAt';
|
||||
|
||||
/**
|
||||
* The direction to sort the results.
|
||||
* @default "desc"
|
||||
*/
|
||||
@ApiPropertyOptional({
|
||||
description: 'Sort direction',
|
||||
enum: sortOrderOptions,
|
||||
default: 'desc',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsIn(sortOrderOptions)
|
||||
order?: SortOrder = 'desc';
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Entity, Index, Property, OneToMany, Collection, Cascade, ManyToOne, Enum } from '@mikro-orm/core';
|
||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||
import { User } from './user.entity';
|
||||
import { WalletTransactionReason, WalletTransactionType } from '../interface/wallet';
|
||||
import { UserWallet } from './user-wallet.entity';
|
||||
|
||||
@Entity({ tableName: 'wallet_transactions' })
|
||||
export class WalletTransaction extends BaseEntity {
|
||||
@ManyToOne(() => UserWallet)
|
||||
userWallet!: UserWallet;
|
||||
|
||||
@Property({ type: 'decimal', precision: 10, scale: 0 })
|
||||
amount!: number;
|
||||
|
||||
@Property({ type: 'decimal', precision: 10, scale: 0 })
|
||||
balance!: number;
|
||||
|
||||
@Enum(() => WalletTransactionType)
|
||||
type!: WalletTransactionType;
|
||||
|
||||
@Enum(() => WalletTransactionReason)
|
||||
reason!: WalletTransactionReason;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export enum WalletTransactionType {
|
||||
CREDIT = 'credit',
|
||||
DEBIT = 'debit',
|
||||
}
|
||||
|
||||
|
||||
export enum WalletTransactionReason {
|
||||
ORDER_PAYMENT = 'order_payment',
|
||||
ORDER_REFUND = 'order_refund',
|
||||
CONVERT_SCORE_TO_WALLET = 'convert_score_to_wallet',
|
||||
WITHDRAW = 'withdraw',
|
||||
DEPOSIT = 'deposit',
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import { UserAddress } from '../entities/user-address.entity';
|
||||
import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { UpdateUserDto } from '../dto/update-user.dto';
|
||||
import { FindUsersDto } from '../dto/find-user.dto';
|
||||
import { FindWalletTransactionsDto } from '../dto/find-wallet-transactions.dto';
|
||||
import { CreateWalletTransactionDto } from '../dto/create-wallet-transaction.dto';
|
||||
import { CreateUserAddressDto } from '../dto/create-user-address.dto';
|
||||
import { UpdateUserAddressDto } from '../dto/update-user-address.dto';
|
||||
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
|
||||
@@ -13,6 +15,7 @@ import { normalizePhone } from '../../utils/phone.util';
|
||||
import { RestRepository } from 'src/modules/restaurants/repositories/rest.repository';
|
||||
import { UserWallet } from '../entities/user-wallet.entity';
|
||||
import { UserWalletRepository } from '../repositories/user-wallet.repository';
|
||||
import { WalletService } from './wallet.service';
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
@@ -20,8 +23,9 @@ export class UserService {
|
||||
private readonly userRepository: UserRepository,
|
||||
private readonly restaurantRepository: RestRepository,
|
||||
private readonly userWalletRepository: UserWalletRepository,
|
||||
private readonly walletService: WalletService,
|
||||
private readonly em: EntityManager,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
async findOrCreateByPhone(phone: string): Promise<User> {
|
||||
const normalizedPhone = normalizePhone(phone);
|
||||
@@ -343,6 +347,15 @@ export class UserService {
|
||||
return user;
|
||||
}
|
||||
getUserWallet(userId: string, restId: string): Promise<UserWallet | null> {
|
||||
return this.userWalletRepository.findOne({ user: { id: userId }, restaurant: { id: restId } });
|
||||
return this.walletService.getUserWallet(userId, restId);
|
||||
}
|
||||
|
||||
getUserWalletTransactions(userId: string, restId: string, dto: FindWalletTransactionsDto) {
|
||||
return this.walletService.getUserWalletTransactions(userId, restId, dto);
|
||||
}
|
||||
|
||||
createWalletTransaction(userId: string, restId: string, dto: CreateWalletTransactionDto) {
|
||||
return this.walletService.createTransaction(userId, restId, dto);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
|
||||
import { FilterQuery } from '@mikro-orm/core';
|
||||
import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { WalletTransaction } from '../entities/wallet-transaction.entity';
|
||||
import { UserWallet } from '../entities/user-wallet.entity';
|
||||
import { WalletTransactionRepository } from '../repositories/wallet-transaction.repository';
|
||||
import { UserWalletRepository } from '../repositories/user-wallet.repository';
|
||||
import { FindWalletTransactionsDto } from '../dto/find-wallet-transactions.dto';
|
||||
import { CreateWalletTransactionDto } from '../dto/create-wallet-transaction.dto';
|
||||
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
|
||||
import { WalletTransactionType } from '../interface/wallet';
|
||||
|
||||
@Injectable()
|
||||
export class WalletService {
|
||||
constructor(
|
||||
private readonly walletTransactionRepository: WalletTransactionRepository,
|
||||
private readonly userWalletRepository: UserWalletRepository,
|
||||
private readonly em: EntityManager,
|
||||
) { }
|
||||
|
||||
async getUserWalletTransactions(
|
||||
userId: string,
|
||||
restId: string,
|
||||
dto: FindWalletTransactionsDto,
|
||||
): Promise<PaginatedResult<WalletTransaction>> {
|
||||
const {
|
||||
page = 1,
|
||||
limit = 10,
|
||||
type,
|
||||
reason,
|
||||
startDate,
|
||||
endDate,
|
||||
minAmount,
|
||||
maxAmount,
|
||||
orderBy = 'createdAt',
|
||||
order = 'desc',
|
||||
} = dto;
|
||||
|
||||
// Calculate pagination
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
// Find the user's wallet for this restaurant
|
||||
const userWallet = await this.userWalletRepository.findOne({
|
||||
user: { id: userId },
|
||||
restaurant: { id: restId },
|
||||
});
|
||||
|
||||
if (!userWallet) {
|
||||
throw new NotFoundException(`User wallet not found for user ${userId} and restaurant ${restId}.`);
|
||||
}
|
||||
|
||||
// Build the 'where' filter query
|
||||
const where: FilterQuery<WalletTransaction> = {
|
||||
userWallet: { id: userWallet.id },
|
||||
};
|
||||
|
||||
// Add type filter
|
||||
if (type) {
|
||||
where.type = type;
|
||||
}
|
||||
|
||||
// Add reason filter
|
||||
if (reason) {
|
||||
where.reason = reason;
|
||||
}
|
||||
|
||||
// Add date range filters
|
||||
if (startDate || endDate) {
|
||||
where.createdAt = {};
|
||||
if (startDate) {
|
||||
where.createdAt.$gte = new Date(startDate);
|
||||
}
|
||||
if (endDate) {
|
||||
where.createdAt.$lte = new Date(endDate);
|
||||
}
|
||||
}
|
||||
|
||||
// Add amount range filters
|
||||
if (minAmount !== undefined || maxAmount !== undefined) {
|
||||
where.amount = {};
|
||||
if (minAmount !== undefined) {
|
||||
where.amount.$gte = minAmount;
|
||||
}
|
||||
if (maxAmount !== undefined) {
|
||||
where.amount.$lte = maxAmount;
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the query using findAndCount
|
||||
const [transactions, total] = await this.walletTransactionRepository.findAndCount(where, {
|
||||
limit,
|
||||
offset,
|
||||
orderBy: { [orderBy]: order.toLowerCase() as 'asc' | 'desc' },
|
||||
});
|
||||
|
||||
// Calculate total pages
|
||||
const totalPages = Math.ceil(total / limit);
|
||||
|
||||
// Return the paginated result
|
||||
return {
|
||||
data: transactions,
|
||||
meta: {
|
||||
total,
|
||||
page,
|
||||
limit,
|
||||
totalPages,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
getUserWallet(userId: string, restId: string): Promise<UserWallet | null> {
|
||||
return this.userWalletRepository.findOne({ user: { id: userId }, restaurant: { id: restId } });
|
||||
}
|
||||
|
||||
async createTransaction(
|
||||
userId: string,
|
||||
restId: string,
|
||||
dto: CreateWalletTransactionDto,
|
||||
): Promise<WalletTransaction> {
|
||||
const { amount, type, reason } = dto;
|
||||
|
||||
// Validate amount
|
||||
if (amount <= 0) {
|
||||
throw new BadRequestException('Transaction amount must be greater than 0.');
|
||||
}
|
||||
|
||||
// Find the user's wallet for this restaurant
|
||||
const userWallet = await this.userWalletRepository.findOne({
|
||||
user: { id: userId },
|
||||
restaurant: { id: restId },
|
||||
});
|
||||
|
||||
if (!userWallet) {
|
||||
throw new NotFoundException(`User wallet not found for user ${userId} and restaurant ${restId}.`);
|
||||
}
|
||||
|
||||
// Calculate new balance
|
||||
const currentBalance = userWallet.wallet || 0;
|
||||
let newBalance: number;
|
||||
|
||||
if (type === WalletTransactionType.CREDIT) {
|
||||
newBalance = currentBalance + amount;
|
||||
} else if (type === WalletTransactionType.DEBIT) {
|
||||
if (currentBalance < amount) {
|
||||
throw new BadRequestException(
|
||||
`Insufficient wallet balance. Current: ${currentBalance}, Required: ${amount}.`,
|
||||
);
|
||||
}
|
||||
newBalance = currentBalance - amount;
|
||||
} else {
|
||||
throw new BadRequestException(`Invalid transaction type: ${type}`);
|
||||
}
|
||||
|
||||
// Use transaction to ensure consistency
|
||||
return await this.em.transactional(async (em) => {
|
||||
// Update wallet balance
|
||||
userWallet.wallet = newBalance;
|
||||
await em.persistAndFlush(userWallet);
|
||||
|
||||
// Create transaction record
|
||||
const transaction = em.create(WalletTransaction, {
|
||||
userWallet,
|
||||
amount,
|
||||
balance: newBalance,
|
||||
type,
|
||||
reason,
|
||||
});
|
||||
|
||||
await em.persistAndFlush(transaction);
|
||||
|
||||
return transaction;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
|
||||
import { WalletTransaction } from '../entities/wallet-transaction.entity';
|
||||
|
||||
@Injectable()
|
||||
export class WalletTransactionRepository extends EntityRepository<WalletTransaction> {
|
||||
constructor(readonly em: EntityManager) {
|
||||
super(em, WalletTransaction);
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,16 @@ import { JwtModule } from '@nestjs/jwt';
|
||||
import { UserRepository } from './repositories/user.repository';
|
||||
import { RestaurantsModule } from '../restaurants/restaurants.module';
|
||||
import { UserWalletRepository } from './repositories/user-wallet.repository';
|
||||
import { WalletTransactionRepository } from './repositories/wallet-transaction.repository';
|
||||
import { WalletService } from './providers/wallet.service';
|
||||
import { UserWallet } from './entities/user-wallet.entity';
|
||||
import { WalletTransaction } from './entities/wallet-transaction.entity';
|
||||
|
||||
@Module({
|
||||
providers: [UserService, UserRepository, UserWalletRepository],
|
||||
providers: [UserService, WalletService, UserRepository, UserWalletRepository, WalletTransactionRepository],
|
||||
controllers: [UsersController],
|
||||
imports: [MikroOrmModule.forFeature([User, UserAddress, UserWallet]), JwtModule, RestaurantsModule],
|
||||
exports: [UserService, UserRepository, UserWalletRepository],
|
||||
imports: [MikroOrmModule.forFeature([User, UserAddress, UserWallet,
|
||||
WalletTransaction]), JwtModule, RestaurantsModule],
|
||||
exports: [UserService, WalletService, UserRepository, UserWalletRepository, WalletTransactionRepository],
|
||||
})
|
||||
export class UserModule {}
|
||||
export class UserModule { }
|
||||
|
||||
Reference in New Issue
Block a user