optimize performance
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-06-18 23:01:44 +03:30
parent 2ce395d1f8
commit 65a34b97e2
+95 -60
View File
@@ -445,73 +445,108 @@ export class UserService {
errors: [], errors: [],
}; };
const validRows: Array<{ row: (typeof rows)[number]; phone: string }> = [];
for (const row of rows) { for (const row of rows) {
try { if (!row.phone) {
if (!row.phone) { result.errors.push({
result.errors.push({ row: row.rowNumber,
row: row.rowNumber, message: UserImportMessage.PHONE_REQUIRED,
message: UserImportMessage.PHONE_REQUIRED, });
}); continue;
continue; }
}
const normalizedPhone = normalizePhone(row.phone); const normalizedPhone = normalizePhone(row.phone);
if (!normalizedPhone) { if (!normalizedPhone) {
result.errors.push({
row: row.rowNumber,
phone: row.phone,
message: UserImportMessage.INVALID_PHONE,
});
continue;
}
let user = await this.userRepository.findOne({ phone: normalizedPhone });
if (!user) {
const createData = {
phone: normalizedPhone,
firstName: row.firstName?.trim() || '[نام]',
lastName: row.lastName?.trim() || undefined,
gender: row.gender,
birthDate: undefined,
marriageDate: undefined,
} as unknown as RequiredEntityData<User>;
user = this.userRepository.create(createData);
await this.em.persistAndFlush(user);
result.usersCreated++;
} else {
const updates: Partial<User> = {};
if (row.firstName?.trim()) {
updates.firstName = row.firstName.trim();
}
if (row.lastName?.trim()) {
updates.lastName = row.lastName.trim();
}
if (row.gender !== undefined) {
updates.gender = row.gender;
}
if (Object.keys(updates).length > 0) {
this.em.assign(user, updates);
await this.em.flush();
}
}
const existingLink = await this.userRestaurantRepository.findOne({ user, restaurant });
if (existingLink) {
result.usersAlreadyLinked++;
continue;
}
await this.addUserToRestaurant(user, restaurant);
result.usersLinked++;
} catch (error) {
result.errors.push({ result.errors.push({
row: row.rowNumber, row: row.rowNumber,
phone: row.phone, phone: row.phone,
message: error instanceof Error ? error.message : 'Unknown error', message: UserImportMessage.INVALID_PHONE,
}); });
continue;
} }
validRows.push({ row, phone: normalizedPhone });
}
if (validRows.length === 0) {
return result;
}
const phones = [...new Set(validRows.map(entry => entry.phone))];
const existingUsers = await this.userRepository.find({ phone: { $in: phones } });
const userByPhone = new Map(existingUsers.map(user => [user.phone, user]));
for (const { row, phone } of validRows) {
let user = userByPhone.get(phone);
if (!user) {
const createData = {
phone,
firstName: row.firstName?.trim() || '[نام]',
lastName: row.lastName?.trim() || undefined,
gender: row.gender,
birthDate: undefined,
marriageDate: undefined,
} as unknown as RequiredEntityData<User>;
user = this.userRepository.create(createData);
userByPhone.set(phone, user);
result.usersCreated++;
} else {
const updates: Partial<User> = {};
if (row.firstName?.trim()) {
updates.firstName = row.firstName.trim();
}
if (row.lastName?.trim()) {
updates.lastName = row.lastName.trim();
}
if (row.gender !== undefined) {
updates.gender = row.gender;
}
if (Object.keys(updates).length > 0) {
this.em.assign(user, updates);
}
}
}
const userIds = [...userByPhone.values()].map(user => user.id);
const existingLinks = await this.userRestaurantRepository.find(
{ restaurant, user: { $in: userIds } },
{ populate: ['user'] },
);
const linkedUserIds = new Set(existingLinks.map(link => link.user.id));
const linkedPhonesInBatch = new Set<string>();
for (const { phone } of validRows) {
const user = userByPhone.get(phone);
if (!user) {
continue;
}
if (linkedUserIds.has(user.id) || linkedPhonesInBatch.has(phone)) {
result.usersAlreadyLinked++;
continue;
}
this.userRestaurantRepository.create({
user,
restaurant,
orderCount: 0,
totalOrderAmount: 0,
});
linkedUserIds.add(user.id);
linkedPhonesInBatch.add(phone);
result.usersLinked++;
}
try {
await this.em.flush();
} catch (error) {
result.errors.push({
row: 0,
message: error instanceof Error ? error.message : 'Unknown error',
});
} }
return result; return result;