initialize git, basic setup for crm

This commit is contained in:
richardtekula
2025-11-18 13:53:28 +01:00
commit da01d586fc
47 changed files with 12776 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
import { db } from '../config/database.js';
import { emails, contacts } from '../db/schema.js';
import { eq, and, or, desc, like, sql } from 'drizzle-orm';
import { NotFoundError } from '../utils/errors.js';
/**
* Get all emails for a user (only from added contacts)
*/
export const getUserEmails = async (userId) => {
const userEmails = await db
.select({
id: emails.id,
jmapId: emails.jmapId,
messageId: emails.messageId,
threadId: emails.threadId,
inReplyTo: emails.inReplyTo,
from: emails.from,
to: emails.to,
subject: emails.subject,
body: emails.body,
isRead: emails.isRead,
date: emails.date,
createdAt: emails.createdAt,
contact: {
id: contacts.id,
email: contacts.email,
name: contacts.name,
},
})
.from(emails)
.leftJoin(contacts, eq(emails.contactId, contacts.id))
.where(eq(emails.userId, userId))
.orderBy(desc(emails.date));
return userEmails;
};
/**
* Get emails by thread ID
*/
export const getEmailThread = async (userId, threadId) => {
const thread = await db
.select()
.from(emails)
.where(and(eq(emails.userId, userId), eq(emails.threadId, threadId)))
.orderBy(emails.date);
if (thread.length === 0) {
throw new NotFoundError('Thread nenájdený');
}
return thread;
};
/**
* Search emails (from, to, subject)
*/
export const searchEmails = async (userId, query) => {
if (!query || query.trim().length < 2) {
throw new Error('Search term must be at least 2 characters');
}
const searchPattern = `%${query}%`;
const results = await db
.select()
.from(emails)
.where(
and(
eq(emails.userId, userId),
or(
like(emails.from, searchPattern),
like(emails.to, searchPattern),
like(emails.subject, searchPattern)
)
)
)
.orderBy(desc(emails.date))
.limit(50);
return results;
};
/**
* Get unread email count
*/
export const getUnreadCount = async (userId) => {
const result = await db
.select({ count: sql`count(*)::int` })
.from(emails)
.where(and(eq(emails.userId, userId), eq(emails.isRead, false)));
return result[0]?.count || 0;
};
/**
* Mark thread as read
*/
export const markThreadAsRead = async (userId, threadId) => {
const result = await db
.update(emails)
.set({ isRead: true, updatedAt: new Date() })
.where(and(eq(emails.userId, userId), eq(emails.threadId, threadId), eq(emails.isRead, false)))
.returning();
return { success: true, count: result.length };
};
/**
* Get emails for a specific contact
*/
export const getContactEmails = async (userId, contactId) => {
const contactEmails = await db
.select()
.from(emails)
.where(and(eq(emails.userId, userId), eq(emails.contactId, contactId)))
.orderBy(desc(emails.date));
return contactEmails;
};