From 65b937d6627461805bd80d62f565e09b9e1c4e0f Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Mon, 9 Feb 2026 15:29:17 +0330 Subject: [PATCH] cart refactored --- src/modules/cart/cart.module.ts | 8 ++ src/modules/cart/interfaces/cart.interface.ts | 4 +- .../providers/cart-calculation.service.ts | 6 +- .../cart/providers/cart-item.service.ts | 34 ++--- .../cart/providers/cart-validation.service.ts | 127 ++++-------------- src/modules/cart/providers/cart.service.ts | 22 +-- src/modules/orders/orders.module.ts | 2 +- .../orders/providers/orders.service.ts | 2 +- .../payments/services/payments.service.ts | 11 +- src/modules/products/product.module.ts | 2 +- src/modules/users/providers/user.service.ts | 8 ++ .../users/repositories/address.repository.ts | 10 ++ src/modules/users/user.module.ts | 11 +- 13 files changed, 109 insertions(+), 138 deletions(-) create mode 100644 src/modules/users/repositories/address.repository.ts diff --git a/src/modules/cart/cart.module.ts b/src/modules/cart/cart.module.ts index 516e1bf..d5eb90f 100644 --- a/src/modules/cart/cart.module.ts +++ b/src/modules/cart/cart.module.ts @@ -20,6 +20,10 @@ import { CartCalculationService } from './providers/cart-calculation.service'; import { CartItemService } from './providers/cart-item.service'; import { PointTransaction } from '../users/entities/point-transaction.entity'; import { WalletTransaction } from '../users/entities/wallet-transaction.entity'; +import { ShopsModule } from '../shops/shops.module'; +import { DeliveryModule } from '../delivery/delivery.module'; +import { ProductModule } from '../products/product.module'; +import { PaymentsModule } from '../payments/payments.module'; @Module({ imports: [ @@ -39,6 +43,10 @@ import { WalletTransaction } from '../users/entities/wallet-transaction.entity'; JwtModule, UtilsModule, CouponModule, + ShopsModule, + DeliveryModule, + ProductModule, + PaymentsModule ], controllers: [CartController], providers: [ diff --git a/src/modules/cart/interfaces/cart.interface.ts b/src/modules/cart/interfaces/cart.interface.ts index 67b611e..bcc0510 100644 --- a/src/modules/cart/interfaces/cart.interface.ts +++ b/src/modules/cart/interfaces/cart.interface.ts @@ -1,8 +1,8 @@ import type { OrderCouponDetail, OrderUserAddress } from 'src/modules/orders/interface/order.interface'; export interface CartItem { - foodId: string; - foodTitle?: string; + productId: string; + productTitle?: string; quantity: number; price: number; discount: number; diff --git a/src/modules/cart/providers/cart-calculation.service.ts b/src/modules/cart/providers/cart-calculation.service.ts index 772120e..ab1379b 100644 --- a/src/modules/cart/providers/cart-calculation.service.ts +++ b/src/modules/cart/providers/cart-calculation.service.ts @@ -14,7 +14,7 @@ export class CartCalculationService { constructor( private readonly em: EntityManager, private readonly couponService: CouponService, - ) {} + ) { } /** * Calculate total price for a cart item @@ -71,7 +71,7 @@ export class CartCalculationService { const foodMap = await this.getFoodsInCartWithCategories(cart); for (const item of cart.items) { - const product = foodMap.get(item.foodId); + const product = foodMap.get(item.productId); if (!product) continue; const matchesCategory = @@ -227,7 +227,7 @@ export class CartCalculationService { * Get products in cart with categories */ private async getFoodsInCartWithCategories(cart: Cart): Promise> { - const foodIds = cart.items.map(item => item.foodId); + const foodIds = cart.items.map(item => item.productId); if (foodIds.length === 0) return new Map(); const products = await this.em.find(Product, { id: { $in: foodIds } }, { populate: ['category'] }); diff --git a/src/modules/cart/providers/cart-item.service.ts b/src/modules/cart/providers/cart-item.service.ts index 6dd3f77..a06cde2 100644 --- a/src/modules/cart/providers/cart-item.service.ts +++ b/src/modules/cart/providers/cart-item.service.ts @@ -4,13 +4,15 @@ import { Cart, CartItem } from '../interfaces/cart.interface'; import { CartValidationService } from './cart-validation.service'; import { CartCalculationService } from './cart-calculation.service'; import { CartMessage } from 'src/common/enums/message.enum'; +import { ProductService } from 'src/modules/products/providers/product.service'; @Injectable() export class CartItemService { constructor( private readonly validationService: CartValidationService, private readonly calculationService: CartCalculationService, - ) {} + private readonly productService: ProductService, + ) { } /** * Create a new cart item from product @@ -20,8 +22,8 @@ export class CartItemService { const itemDiscount = product.discount || 0; return { - foodId: product.id, - foodTitle: product.title, + productId: product.id, + productTitle: product.title, quantity, price: itemPrice, discount: itemDiscount, @@ -37,8 +39,8 @@ export class CartItemService { const itemDiscount = product.discount || 0; return { ...(previous ?? ({} as CartItem)), - foodId: product.id, - foodTitle: product.title, + productId: product.id, + productTitle: product.title, quantity, price: itemPrice, discount: itemDiscount, @@ -49,16 +51,16 @@ export class CartItemService { /** * Get item index in cart */ - getItemIndex(cart: Cart, foodId: string): number { - return cart.items.findIndex(item => item.foodId === foodId); + getItemIndex(cart: Cart, shopId: string): number { + return cart.items.findIndex(item => item.productId === shopId); } /** * Add or increment item in cart */ - async addOrIncrementItem(cart: Cart, foodId: string, restaurantId: string, quantityToAdd: number): Promise { - const product = await this.validationService.validateAndGetFood(foodId, restaurantId, quantityToAdd); - + async addOrIncrementItem(cart: Cart, shopId: string, restaurantId: string, quantityToAdd: number): Promise { + const product = await this.validationService.validateAndGetFood(shopId, restaurantId, quantityToAdd); + const index = this.getItemIndex(cart, product.id); if (index < 0) { @@ -68,15 +70,15 @@ export class CartItemService { const existingItem = cart.items[index]; const newQuantity = existingItem.quantity + quantityToAdd; - this.validationService.validateStock(product, newQuantity); + cart.items[index] = this.buildCartItemFromFood(product, newQuantity, existingItem); } /** * Remove item from cart */ - removeItemOrFail(cart: Cart, foodId: string): void { - const itemIndex = this.getItemIndex(cart, foodId); + removeItemOrFail(cart: Cart, shopId: string): void { + const itemIndex = this.getItemIndex(cart, shopId); if (itemIndex < 0) { throw new NotFoundException(CartMessage.ITEM_NOT_FOUND); } @@ -86,8 +88,8 @@ export class CartItemService { /** * Decrement item quantity or remove if quantity reaches 0 */ - async decrementOrRemoveItem(cart: Cart, foodId: string): Promise { - const itemIndex = this.getItemIndex(cart, foodId); + async decrementOrRemoveItem(cart: Cart, shopId: string): Promise { + const itemIndex = this.getItemIndex(cart, shopId); if (itemIndex < 0) { throw new NotFoundException(CartMessage.ITEM_NOT_FOUND); } @@ -100,7 +102,7 @@ export class CartItemService { return; } - const product = await this.validationService.getFoodOrFail(foodId); + const product = await this.productService.findOrFail(shopId); cart.items[itemIndex] = this.buildCartItemFromFood(product, newQuantity, existingItem); } } diff --git a/src/modules/cart/providers/cart-validation.service.ts b/src/modules/cart/providers/cart-validation.service.ts index b83b03d..7493fdf 100644 --- a/src/modules/cart/providers/cart-validation.service.ts +++ b/src/modules/cart/providers/cart-validation.service.ts @@ -1,37 +1,40 @@ import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common'; import { EntityManager } from '@mikro-orm/postgresql'; import { Product } from 'src/modules/products/entities/product.entity'; -import { Shop } from 'src/modules/shops/entities/shop.entity'; import { UserAddress } from 'src/modules/users/entities/user-address.entity'; -import { User } from 'src/modules/users/entities/user.entity'; import { PaymentMethod } from 'src/modules/payments/entities/payment-method.entity'; import { Delivery } from 'src/modules/delivery/entities/delivery.entity'; import { DeliveryMethodEnum } from 'src/modules/delivery/interface/delivery'; -import { PointTransaction } from 'src/modules/users/entities/point-transaction.entity'; import { Order } from 'src/modules/orders/entities/order.entity'; import { OrderStatus } from 'src/modules/orders/interface/order.interface'; import { Cart } from '../interfaces/cart.interface'; import { GeographicUtils } from '../utils/geographic.utils'; import { CartMessage } from 'src/common/enums/message.enum'; import { WalletTransactionRepository } from 'src/modules/users/repositories/wallet-transaction.repository'; +import { ProductService } from 'src/modules/products/providers/product.service'; +import { ShopService } from 'src/modules/shops/providers/shops.service'; +import { DeliveryService } from 'src/modules/delivery/providers/delivery.service'; +import { PaymentsService } from 'src/modules/payments/services/payments.service'; +import { PaymentMethodService } from 'src/modules/payments/services/payment-method.service'; @Injectable() export class CartValidationService { constructor( private readonly em: EntityManager, private readonly walletTransactionRepository: WalletTransactionRepository, + private readonly productService: ProductService, + private readonly shopService: ShopService, + private readonly deliveryService: DeliveryService, + private readonly paymentMethodService: PaymentMethodService, ) { } /** * Validate product exists and belongs to shop */ - async validateAndGetFood(foodId: string, restaurantId: string, quantity: number): Promise { - const product = await this.em.findOne(Product, { id: foodId }, { populate: ['shop'] }); - if (!product) { - throw new NotFoundException(CartMessage.PRODUCT_NOT_FOUND); - } + async validateAndGetFood(productId: string, shopId: string, quantity: number): Promise { + const product = await this.productService.findOrFail(productId) - if (product.shop.id !== restaurantId) { + if (product.shop.id !== shopId) { throw new BadRequestException(CartMessage.PRODUCT_NOT_BELONGS_TO_SHOP); } @@ -39,50 +42,6 @@ export class CartValidationService { } - /** - * Get user or throw if not found - */ - async getUserOrFail(userId: string): Promise { - const user = await this.em.findOne(User, { id: userId }); - if (!user) { - throw new NotFoundException(CartMessage.USER_NOT_FOUND); - } - return user; - } - - /** - * Get user address or throw if not found - */ - async getUserAddressOrFail(addressId: string): Promise { - const address = await this.em.findOne(UserAddress, { id: addressId }, { populate: ['user'] }); - if (!address) { - throw new NotFoundException(CartMessage.ADDRESS_NOT_FOUND); - } - return address; - } - - /** - * Get product or throw if not found - */ - async getFoodOrFail(foodId: string): Promise { - const product = await this.em.findOne(Product, { id: foodId }); - if (!product) { - throw new NotFoundException(CartMessage.PRODUCT_NOT_FOUND); - } - return product; - } - - /** - * Get shop or throw if not found - */ - async getRestaurantOrFail(restaurantId: string): Promise { - const shop = await this.em.findOne(Shop, { id: restaurantId }); - if (!shop) { - throw new NotFoundException(CartMessage.SHOP_NOT_FOUND); - } - return shop; - } - /** * Validate address belongs to user */ @@ -96,7 +55,7 @@ export class CartValidationService { * Assert address is inside shop service area */ async assertAddressInsideServiceArea( - restaurantId: string, + shopId: string, latitude?: number | null, longitude?: number | null, ): Promise { @@ -104,7 +63,7 @@ export class CartValidationService { throw new BadRequestException(CartMessage.ADDRESS_NO_COORDINATES); } - const shop = await this.getRestaurantOrFail(restaurantId); + const shop = await this.shopService.findOrFail(shopId); const serviceArea = shop.serviceArea; // If no service area is defined, assume service is available everywhere @@ -130,34 +89,13 @@ export class CartValidationService { /** * Get delivery method for shop or throw if not found */ - async getDeliveryMethodForRestaurantOrFail( - restaurantId: string, - deliveryMethodId: string, - ): Promise { - const deliveryMethod = await this.em.findOne(Delivery, { - id: deliveryMethodId, - shop: { id: restaurantId }, - }); - if (!deliveryMethod) { - throw new NotFoundException(CartMessage.DELIVERY_METHOD_NOT_FOUND_FOR_SHOP); - } - - return deliveryMethod; - } /** * Get enabled delivery method or throw if not found or disabled */ - async getEnabledDeliveryMethodOrFail(restaurantId: string, deliveryMethodId: string): Promise { - const deliveryMethod = await this.em.findOne( - Delivery, - { id: deliveryMethodId, shop: { id: restaurantId } }, - { populate: ['shop'] }, - ); - if (!deliveryMethod) { - throw new NotFoundException(CartMessage.DELIVERY_METHOD_NOT_FOUND); - } + async getEnabledDeliveryMethodOrFail(shopId: string, deliveryMethodId: string): Promise { + const deliveryMethod = await this.deliveryService.findOrFail(shopId, deliveryMethodId) if (!deliveryMethod.enabled) { throw new BadRequestException(CartMessage.DELIVERY_METHOD_NOT_ENABLED); } @@ -186,14 +124,10 @@ export class CartValidationService { /** * Get enabled payment method or throw if not found or disabled */ - async getEnabledPaymentMethodOrFail(restaurantId: string, paymentMethodId: string): Promise { - const paymentMethod = await this.em.findOne( - PaymentMethod, - { id: paymentMethodId, shop: { id: restaurantId } }, - { populate: ['shop'] }, - ); - if (!paymentMethod) { - throw new NotFoundException(CartMessage.PAYMENT_METHOD_NOT_FOUND); + async getEnabledPaymentMethodOrFail(shopId: string, paymentMethodId: string): Promise { + const paymentMethod = await this.paymentMethodService.findOneOrFail(paymentMethodId) + if (paymentMethod.shop.id !== shopId) { + throw new BadRequestException('CartMessage.PAYMENT_METHOD_NOT_BELONGS_TO_SHOP'); } if (!paymentMethod.enabled) { throw new BadRequestException(CartMessage.PAYMENT_METHOD_NOT_ENABLED); @@ -204,8 +138,8 @@ export class CartValidationService { /** * Assert wallet has enough balance */ - async assertWalletHasEnoughBalance(userId: string, restaurantId: string, amount: number): Promise { - const balance = await this.walletTransactionRepository.getCurrentWalletBalance(userId, restaurantId); + async assertWalletHasEnoughBalance(userId: string, shopId: string, amount: number): Promise { + const balance = await this.walletTransactionRepository.getCurrentWalletBalance(userId, shopId); if (balance < amount) { throw new BadRequestException(CartMessage.WALLET_INSUFFICIENT); @@ -247,7 +181,7 @@ export class CartValidationService { const foodMap = await this.getFoodsInCartWithCategories(cart); for (const item of cart.items) { - const product = foodMap.get(item.foodId); + const product = foodMap.get(item.productId); if (!product) continue; const matchesCategory = hasCategoryRestriction && product.category && categoryRestriction.includes(product.category.id); @@ -262,19 +196,14 @@ export class CartValidationService { * Get products in cart with categories */ async getFoodsInCartWithCategories(cart: Cart): Promise> { - const foodIds = cart.items.map(item => item.foodId); - if (foodIds.length === 0) return new Map(); + const productIds = cart.items.map(item => item.productId); + if (productIds.length === 0) return new Map(); - const products = await this.em.find(Product, { id: { $in: foodIds } }, { populate: ['category'] }); + const products = await this.em.find(Product, { id: { $in: productIds } }, { populate: ['category'] }); return new Map(products.map(f => [f.id, f])); } - /** - * Validate stock for a product - */ - validateStock(product: Product, quantity: number): void { - // TODO: Implement stock validation logic - // For now, assume unlimited stock - } + + } diff --git a/src/modules/cart/providers/cart.service.ts b/src/modules/cart/providers/cart.service.ts index fb9a2a3..e433cec 100644 --- a/src/modules/cart/providers/cart.service.ts +++ b/src/modules/cart/providers/cart.service.ts @@ -12,6 +12,9 @@ import { CartValidationService } from './cart-validation.service'; import { CartCalculationService } from './cart-calculation.service'; import { CartItemService } from './cart-item.service'; import { CartMessage } from 'src/common/enums/message.enum'; +import { UserService } from 'src/modules/users/providers/user.service'; +import { ShopService } from 'src/modules/shops/providers/shops.service'; +import { DeliveryService } from 'src/modules/delivery/providers/delivery.service'; @Injectable() export class CartService { @@ -21,6 +24,9 @@ export class CartService { private readonly calculationService: CartCalculationService, private readonly itemService: CartItemService, private readonly couponService: CouponService, + private readonly userService: UserService, + private readonly shopService: ShopService, + private readonly deliveryService: DeliveryService, ) { } /** @@ -54,7 +60,7 @@ export class CartService { throw new BadRequestException(CartMessage.ADDRESS_REQUIRED); } this.clearFieldsIncompatibleWithDeliveryMethod(cart, DeliveryMethodEnum.DeliveryCourier); - const address = await this.validationService.getUserAddressOrFail(addressId); + const address = await this.userService.getUserAddressOrFail(addressId); this.validationService.validateAddressOwnership(address, userId); // ensure address is within shop service area @@ -111,7 +117,7 @@ export class CartService { } // Find shop - const shop = await this.validationService.getRestaurantOrFail(restaurantId); + const shop = await this.shopService.findOrFail(restaurantId); // Create new cart const now = this.nowIso(); @@ -194,7 +200,7 @@ export class CartService { const cart = await this.findOneOrFail(userId, restaurantId); const orderAmount = cart.subTotal - cart.itemsDiscount; - const user = await this.validationService.getUserOrFail(userId); + const user = await this.userService.findOneOrFail(userId); // check if coupon is valid and belong to the shop const { valid, coupon, message } = await this.couponService.validateCoupon( applyCouponDto.code, @@ -252,10 +258,8 @@ export class CartService { cart, 'Delivery method must be set before setting address', ); - const deliveryMethod = await this.validationService.getDeliveryMethodForRestaurantOrFail( - restaurantId, - deliveryMethodId, - ); + const deliveryMethod = await this.deliveryService.findOrFail(restaurantId, deliveryMethodId); + this.validationService.assertDeliveryMethod( deliveryMethod.method, DeliveryMethodEnum.DeliveryCourier, @@ -263,7 +267,7 @@ export class CartService { ); // Find and validate address belongs to user - const address = await this.validationService.getUserAddressOrFail(addressId); + const address = await this.userService.getUserAddressOrFail(addressId); // Verify address belongs to the user this.validationService.validateAddressOwnership(address, userId); @@ -354,7 +358,6 @@ export class CartService { */ private clearFieldsIncompatibleWithDeliveryMethod(cart: Cart, method: DeliveryMethodEnum): void { - if (method === DeliveryMethodEnum.CustomerPickup) { cart.userAddress = null; cart.tableNumber = undefined; @@ -366,7 +369,6 @@ export class CartService { return; } - } /** diff --git a/src/modules/orders/orders.module.ts b/src/modules/orders/orders.module.ts index 11e7062..f5e1b03 100644 --- a/src/modules/orders/orders.module.ts +++ b/src/modules/orders/orders.module.ts @@ -27,7 +27,7 @@ import { DeliveryModule } from '../delivery/delivery.module'; @Module({ imports: [ MikroOrmModule.forFeature([Order, OrderItem, User, Shop, Product, Variant, UserAddress, PaymentMethod]), - CartModule, + forwardRef(() => CartModule), UtilsModule, AuthModule, forwardRef(() => PaymentsModule), diff --git a/src/modules/orders/providers/orders.service.ts b/src/modules/orders/providers/orders.service.ts index 989cbb6..8034c3e 100644 --- a/src/modules/orders/providers/orders.service.ts +++ b/src/modules/orders/providers/orders.service.ts @@ -366,7 +366,7 @@ export class OrdersService { const orderItemsData: OrderItemData[] = []; for (const cartItem of cart.items) { - const variant = await this.em.findOne(Variant, { id: cartItem.foodId }, { populate: ['product', 'product.shop'] }); + const variant = await this.em.findOne(Variant, { id: cartItem.productId }, { populate: ['product', 'product.shop'] }); if (!variant) throw new NotFoundException(OrderMessage.PRODUCT_NOT_FOUND); if (variant.product.shop.id !== shopId) { diff --git a/src/modules/payments/services/payments.service.ts b/src/modules/payments/services/payments.service.ts index bbf0f14..0d0b0a5 100644 --- a/src/modules/payments/services/payments.service.ts +++ b/src/modules/payments/services/payments.service.ts @@ -13,6 +13,7 @@ import { PaymentMessage, OrderMessage } from 'src/common/enums/message.enum'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { onlinePaymentSucceedEvent, paymentSucceedEvent } from '../events/payment.events'; import { WalletTransactionReason, WalletTransactionType } from 'src/modules/users/interface/wallet'; +import { PaymentRepository } from '../repositories/payment.repository'; @Injectable() export class PaymentsService { @@ -22,6 +23,7 @@ export class PaymentsService { private readonly em: EntityManager, private readonly gatewayManager: GatewayManager, private readonly eventEmitter: EventEmitter2, + private readonly paymentRepository: PaymentRepository, ) { } async payOrder(orderId: string): Promise<{ paymentUrl: string | null }> { @@ -141,7 +143,7 @@ export class PaymentsService { payment.paidAt = new Date(); order.status = OrderStatus.PAID; - em.persist([ payment, order, newWalletTransaction]); + em.persist([payment, order, newWalletTransaction]); await em.flush(); }); this.eventEmitter.emit( @@ -278,6 +280,13 @@ export class PaymentsService { payment.order.status = OrderStatus.CANCELED; } + async findOneOrFail(paymentId: string): Promise { + const payment=await this.paymentRepository.findOne({ id: paymentId }); + if (!payment) { + throw new NotFoundException(PaymentMessage.PAYMENT_NOT_FOUND); + } + return payment; + } private async getOrCreateLatestPendingPayment( orderId: string, diff --git a/src/modules/products/product.module.ts b/src/modules/products/product.module.ts index dcd15f8..4e9ea10 100644 --- a/src/modules/products/product.module.ts +++ b/src/modules/products/product.module.ts @@ -25,6 +25,6 @@ import { Favorite } from './entities/favorite.entity'; ], controllers: [FoodController, CategoryController], providers: [ProductService, CategoryService, ProductRepository, CategoryRepository], - exports: [ProductRepository, CategoryRepository], + exports: [ProductRepository, CategoryRepository, ProductService], }) export class ProductModule {} diff --git a/src/modules/users/providers/user.service.ts b/src/modules/users/providers/user.service.ts index b538da0..c4972ab 100644 --- a/src/modules/users/providers/user.service.ts +++ b/src/modules/users/providers/user.service.ts @@ -392,4 +392,12 @@ export class UserService { } return user; } + + async getUserAddressOrFail(addressId: string): Promise { + const address = await this.em.findOne(UserAddress, { id: addressId }, { populate: ['user'] }); + if (!address) { + throw new NotFoundException("User address not found."); + } + return address; + } } diff --git a/src/modules/users/repositories/address.repository.ts b/src/modules/users/repositories/address.repository.ts new file mode 100644 index 0000000..a8936d8 --- /dev/null +++ b/src/modules/users/repositories/address.repository.ts @@ -0,0 +1,10 @@ +import { Injectable } from '@nestjs/common'; +import { EntityManager, EntityRepository } from '@mikro-orm/postgresql'; +import { UserAddress } from '../entities/user-address.entity'; + +@Injectable() +export class AddressRepository extends EntityRepository { + constructor(readonly em: EntityManager) { + super(em, UserAddress); + } +} diff --git a/src/modules/users/user.module.ts b/src/modules/users/user.module.ts index 61bc4d5..f5b93c1 100644 --- a/src/modules/users/user.module.ts +++ b/src/modules/users/user.module.ts @@ -6,21 +6,24 @@ import { User } from './entities/user.entity'; import { UserAddress } from './entities/user-address.entity'; import { JwtModule } from '@nestjs/jwt'; import { UserRepository } from './repositories/user.repository'; - import { WalletTransactionRepository } from './repositories/wallet-transaction.repository'; +import { WalletTransactionRepository } from './repositories/wallet-transaction.repository'; import { WalletService } from './providers/wallet.service'; import { WalletTransaction } from './entities/wallet-transaction.entity'; import { PointTransaction } from './entities/point-transaction.entity'; import { PointTransactionRepository } from './repositories/point-transaction.repository'; import { ShopsModule } from '../shops/shops.module'; +import { AddressRepository } from './repositories/address.repository'; @Module({ - providers: [UserService, WalletService, UserRepository, WalletTransactionRepository, PointTransactionRepository], + providers: [UserService, WalletService, UserRepository, + WalletTransactionRepository, PointTransactionRepository, AddressRepository], controllers: [UsersController], imports: [ MikroOrmModule.forFeature([User, UserAddress, WalletTransaction, PointTransaction]), JwtModule, ShopsModule ], - exports: [UserService, WalletService, UserRepository, WalletTransactionRepository, PointTransactionRepository], + exports: [UserService, WalletService, UserRepository, + WalletTransactionRepository, PointTransactionRepository, AddressRepository], }) -export class UserModule {} +export class UserModule { }