101 lines
2.8 KiB
JavaScript
101 lines
2.8 KiB
JavaScript
import { and, desc, eq, inArray } from 'drizzle-orm';
|
|
import { db } from '../config/database.js';
|
|
import { contacts, emailAccounts, emails, userEmailAccounts } from '../db/schema.js';
|
|
|
|
export const getCompanyEmailThreads = async (companyId, userId) => {
|
|
const accountLinks = await db
|
|
.select({
|
|
id: emailAccounts.id,
|
|
email: emailAccounts.email,
|
|
isActive: emailAccounts.isActive,
|
|
})
|
|
.from(userEmailAccounts)
|
|
.innerJoin(emailAccounts, eq(userEmailAccounts.emailAccountId, emailAccounts.id))
|
|
.where(
|
|
and(
|
|
eq(userEmailAccounts.userId, userId),
|
|
eq(emailAccounts.isActive, true)
|
|
)
|
|
);
|
|
|
|
const accountIds = accountLinks.map((acc) => acc.id);
|
|
|
|
if (accountIds.length === 0) {
|
|
return { accounts: [], threads: [] };
|
|
}
|
|
|
|
const rows = await db
|
|
.select({
|
|
threadId: emails.threadId,
|
|
emailAccountId: emails.emailAccountId,
|
|
accountEmail: emailAccounts.email,
|
|
subject: emails.subject,
|
|
date: emails.date,
|
|
isRead: emails.isRead,
|
|
from: emails.from,
|
|
to: emails.to,
|
|
contactId: contacts.id,
|
|
contactEmail: contacts.email,
|
|
contactName: contacts.name,
|
|
})
|
|
.from(emails)
|
|
.innerJoin(emailAccounts, eq(emails.emailAccountId, emailAccounts.id))
|
|
.leftJoin(contacts, eq(emails.contactId, contacts.id))
|
|
.where(
|
|
and(
|
|
inArray(emails.emailAccountId, accountIds),
|
|
eq(emails.companyId, companyId)
|
|
)
|
|
)
|
|
.orderBy(desc(emails.date));
|
|
|
|
const threadsMap = new Map();
|
|
|
|
for (const row of rows) {
|
|
const threadKey = `${row.emailAccountId}:${row.threadId}`;
|
|
const lastDate = row.date ? new Date(row.date) : null;
|
|
const existing = threadsMap.get(threadKey);
|
|
|
|
if (!existing) {
|
|
threadsMap.set(threadKey, {
|
|
threadId: row.threadId,
|
|
emailAccountId: row.emailAccountId,
|
|
accountEmail: row.accountEmail,
|
|
contactId: row.contactId,
|
|
contactEmail: row.contactEmail,
|
|
contactName: row.contactName,
|
|
subject: row.subject,
|
|
lastFrom: row.from,
|
|
lastTo: row.to,
|
|
lastMessageAt: lastDate,
|
|
unreadCount: row.isRead ? 0 : 1,
|
|
totalCount: 1,
|
|
});
|
|
continue;
|
|
}
|
|
|
|
existing.totalCount += 1;
|
|
if (!row.isRead) {
|
|
existing.unreadCount += 1;
|
|
}
|
|
|
|
if (lastDate && (!existing.lastMessageAt || lastDate > existing.lastMessageAt)) {
|
|
existing.lastMessageAt = lastDate;
|
|
existing.subject = row.subject;
|
|
existing.lastFrom = row.from;
|
|
existing.lastTo = row.to;
|
|
}
|
|
}
|
|
|
|
const threads = Array.from(threadsMap.values()).sort((a, b) => {
|
|
const aTime = a.lastMessageAt ? a.lastMessageAt.getTime() : 0;
|
|
const bTime = b.lastMessageAt ? b.lastMessageAt.getTime() : 0;
|
|
return bTime - aTime;
|
|
});
|
|
|
|
return {
|
|
accounts: accountLinks,
|
|
threads,
|
|
};
|
|
};
|