100 lines
2.7 KiB
TypeScript
100 lines
2.7 KiB
TypeScript
import 'server-only';
|
|
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
|
|
import type { Database } from '@kit/supabase/database';
|
|
|
|
interface CommunicationListOptions {
|
|
type?: string;
|
|
direction?: string;
|
|
search?: string;
|
|
page?: number;
|
|
pageSize?: number;
|
|
}
|
|
|
|
interface CreateCommunicationInput {
|
|
accountId: string;
|
|
entityId: string;
|
|
type: string;
|
|
direction?: string;
|
|
subject?: string;
|
|
body?: string;
|
|
emailTo?: string;
|
|
emailCc?: string;
|
|
attachmentPaths?: string[];
|
|
}
|
|
|
|
export function createEventCommunicationService(
|
|
client: SupabaseClient<Database>,
|
|
) {
|
|
return new EventCommunicationService(client);
|
|
}
|
|
|
|
class EventCommunicationService {
|
|
constructor(private readonly client: SupabaseClient<Database>) {}
|
|
|
|
async list(
|
|
eventId: string,
|
|
accountId: string,
|
|
opts?: CommunicationListOptions,
|
|
) {
|
|
let query = (this.client.from as CallableFunction)('module_communications')
|
|
.select('*', { count: 'exact' })
|
|
.eq('module', 'events')
|
|
.eq('entity_id', eventId)
|
|
.eq('account_id', accountId)
|
|
.order('created_at', { ascending: false });
|
|
|
|
if (opts?.type) query = query.eq('type', opts.type);
|
|
if (opts?.direction) query = query.eq('direction', opts.direction);
|
|
if (opts?.search) {
|
|
const escaped = opts.search.replace(/[%_\\]/g, '\\$&');
|
|
query = query.or(`subject.ilike.%${escaped}%,body.ilike.%${escaped}%`);
|
|
}
|
|
|
|
const page = opts?.page ?? 1;
|
|
const pageSize = opts?.pageSize ?? 25;
|
|
query = query.range((page - 1) * pageSize, page * pageSize - 1);
|
|
|
|
const { data, error, count } = await query;
|
|
if (error) throw error;
|
|
return { data: data ?? [], total: count ?? 0, page, pageSize };
|
|
}
|
|
|
|
async create(input: CreateCommunicationInput, userId: string) {
|
|
const { data, error } = await (this.client.from as CallableFunction)(
|
|
'module_communications',
|
|
)
|
|
.insert({
|
|
account_id: input.accountId,
|
|
module: 'events',
|
|
entity_id: input.entityId,
|
|
type: input.type,
|
|
direction: input.direction ?? 'internal',
|
|
subject: input.subject ?? null,
|
|
body: input.body ?? null,
|
|
email_to: input.emailTo ?? null,
|
|
email_cc: input.emailCc ?? null,
|
|
attachment_paths: input.attachmentPaths ?? null,
|
|
created_by: userId,
|
|
})
|
|
.select(
|
|
'id, account_id, module, entity_id, type, direction, subject, email_to, created_at, created_by',
|
|
)
|
|
.single();
|
|
|
|
if (error) throw error;
|
|
return data;
|
|
}
|
|
|
|
async delete(communicationId: string) {
|
|
const { error } = await (this.client.from as CallableFunction)(
|
|
'module_communications',
|
|
)
|
|
.delete()
|
|
.eq('id', communicationId)
|
|
.eq('module', 'events');
|
|
|
|
if (error) throw error;
|
|
}
|
|
}
|