This commit is contained in:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user