update customers

This commit is contained in:
2026-06-18 20:15:05 +03:30
parent e1823d2722
commit 136b067d37
8 changed files with 285 additions and 18 deletions
@@ -72,6 +72,9 @@ export class AuthService {
if (!rest) {
throw new BadRequestException(RestMessage.NOT_FOUND);
}
// add user to restuarant
await this.userService.addUserToRestaurant(user, rest);
const tokens = await this.tokensService.generateAccessAndRefreshToken(user.id, rest.id, false, slug);
@@ -179,7 +179,7 @@ export class UsersController {
query: FindUsersDto,
@RestId() restId: string,
) {
return this.userService.findAll(restId, query);
return this.userService.findPaginated(restId, query);
}
@UseGuards(AdminAuthGuard)
@@ -0,0 +1,22 @@
import { Entity, ManyToOne, Index, Property, Unique } from '@mikro-orm/core';
import { BaseEntity } from '../../../common/entities/base.entity';
import { User } from './user.entity';
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
@Entity({ tableName: 'user_restuarant' })
@Index({ properties: ['restaurant'] })
@Unique({ properties: ['user', 'restaurant'] })
export class UserRestaurant extends BaseEntity {
@ManyToOne(() => User)
user!: User;
@ManyToOne(() => Restaurant)
restaurant!: Restaurant;
@Property({ type: 'integer' })
orderCount!: number;
@Property({ type: 'integer' })
totalOrderAmount!: number;
}
+45 -14
View File
@@ -18,6 +18,8 @@ import { WalletTransactionRepository } from '../repositories/wallet-transaction.
import { WalletService } from './wallet.service';
import { WalletTransactionReason, WalletTransactionType } from '../interface/wallet';
import { WalletTransaction } from '../entities/wallet-transaction.entity';
import { UserRestaurantRepository } from '../repositories/user-restuarant.repository';
import { UserRestaurant } from '../entities/user-restuarant.entity';
@Injectable()
export class UserService {
@@ -27,6 +29,7 @@ export class UserService {
private readonly walletTransactionRepository: WalletTransactionRepository,
private readonly walletService: WalletService,
private readonly em: EntityManager,
private readonly userRestaurantRepository: UserRestaurantRepository,
) { }
async findOrCreateByPhone(phone: string): Promise<User> {
@@ -129,18 +132,16 @@ export class UserService {
return user;
}
async findAll(restId: string, dto: FindUsersDto): Promise<PaginatedResult<User>> {
async findPaginated(restId: string, dto: FindUsersDto): Promise<PaginatedResult<UserRestaurant>> {
const { page = 1, limit = 10, search, orderBy = 'createdAt', order = 'desc' } = dto;
// 1. Calculate pagination
const offset = (page - 1) * limit;
// 2. Build the 'where' filter query
const where: FilterQuery<User> = {
orders: {
restaurant: {
id: restId,
},
const where: FilterQuery<UserRestaurant> = {
restaurant: {
id: restId,
},
};
@@ -151,19 +152,22 @@ export class UserService {
const normalizedSearchPattern = `%${normalizedSearch}%`;
// $ilike is case-insensitive (PostgreSQL). Use $like for MySQL (often CI by default)
// Search with both original and normalized phone patterns to handle various input formats
where.$or = [
{ firstName: { $ilike: searchPattern } },
{ lastName: { $ilike: searchPattern } },
{ phone: { $ilike: searchPattern } },
...(normalizedSearch !== search ? [{ phone: { $ilike: normalizedSearchPattern } }] : []),
];
where.user = {
$or: [
{ firstName: { $ilike: searchPattern } },
{ lastName: { $ilike: searchPattern } },
{ phone: { $ilike: searchPattern } },
...(normalizedSearch !== search ? [{ phone: { $ilike: normalizedSearchPattern } }] : []),
],
};
}
// 5. Execute the query using findAndCount
const [users, total] = await this.userRepository.findAndCount(where, {
const [userRestaurants, total] = await this.userRestaurantRepository.findAndCount(where, {
limit,
offset,
orderBy: { [orderBy]: order.toLowerCase() as 'asc' | 'desc' },
populate: ['user'],
});
// 6. Calculate total pages
@@ -171,7 +175,7 @@ export class UserService {
// 7. Return the paginated result
return {
data: users,
data: userRestaurants,
meta: {
total,
page,
@@ -225,6 +229,33 @@ export class UserService {
return address;
}
// add user to retuarant customers list
async addUserToRestaurant(user: User, restaurant: Restaurant) {
// const restaurant = await this.restaurantRepository.findOne({ id: restId });
// if (!restaurant) {
// throw new NotFoundException(`Restaurant with ID ${restId} not found.`);
// }
// const user = await this.userRepository.findOne({ id: userId });
// if (!user) {
// throw new NotFoundException(`User with ID ${userId} not found.`);
// }
const existingUSer = await this.userRestaurantRepository.findOne({ user, restaurant });
if (existingUSer) {
return existingUSer;
}
const userRestaurant = this.userRestaurantRepository.create({
user,
restaurant,
orderCount: 0,
totalOrderAmount: 0,
});
await this.em.persistAndFlush(userRestaurant);
return userRestaurant;
}
async getUserAddress(userId: string, addressId: string): Promise<UserAddress> {
const address = await this.em.findOne(UserAddress, {
id: addressId,
@@ -0,0 +1,10 @@
import { Injectable } from '@nestjs/common';
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
import { UserRestaurant } from '../entities/user-restuarant.entity';
@Injectable()
export class UserRestaurantRepository extends EntityRepository<UserRestaurant> {
constructor(readonly em: EntityManager) {
super(em, UserRestaurant);
}
}
+7 -3
View File
@@ -12,15 +12,19 @@ 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 { UserRestaurant } from './entities/user-restuarant.entity';
import { UserRestaurantRepository } from './repositories/user-restuarant.repository';
@Module({
providers: [UserService, WalletService, UserRepository, WalletTransactionRepository, PointTransactionRepository],
providers: [UserService, WalletService,
UserRepository, WalletTransactionRepository,
PointTransactionRepository, UserRestaurantRepository],
controllers: [UsersController],
imports: [
MikroOrmModule.forFeature([User, UserAddress, WalletTransaction, PointTransaction]),
MikroOrmModule.forFeature([User, UserAddress, WalletTransaction, PointTransaction, UserRestaurant]),
JwtModule,
RestaurantsModule,
],
exports: [UserService, WalletService, UserRepository, WalletTransactionRepository, PointTransactionRepository],
})
export class UserModule {}
export class UserModule { }