This commit is contained in:
phaichayon
2026-07-01 08:44:35 +07:00
parent 0c39472dca
commit 6d6cd3a6df
32 changed files with 1284 additions and 333 deletions

View File

@@ -0,0 +1,86 @@
export const CRM_ACTIVITY_ENTITY_TYPES = [
'lead',
'opportunity',
'quotation',
'customer',
'contact',
'purchase_order',
'service_report'
] as const;
export const CRM_ACTIVITY_TYPES = [
'site_visit',
'meeting',
'phone_call',
'email_follow_up',
'quotation_follow_up',
'site_survey',
'requirement_discussion',
'internal_task',
'other'
] as const;
export const CRM_ACTIVITY_STATUSES = [
'planned',
'in_progress',
'completed',
'cancelled',
'overdue'
] as const;
export const CRM_ACTIVITY_PRIORITIES = ['low', 'medium', 'high', 'urgent'] as const;
export type CrmActivityEntityType = (typeof CRM_ACTIVITY_ENTITY_TYPES)[number];
export type CrmActivityType = (typeof CRM_ACTIVITY_TYPES)[number];
export type CrmActivityStatus = (typeof CRM_ACTIVITY_STATUSES)[number];
export type CrmActivityPriority = (typeof CRM_ACTIVITY_PRIORITIES)[number];
export interface CrmActivityRecord {
id: string;
organizationId: string;
entityType: CrmActivityEntityType;
entityId: string;
activityType: CrmActivityType;
subject: string;
description: string | null;
ownerId: string | null;
assignedToId: string | null;
dueDate: string | null;
dueTime: string | null;
completedAt: string | null;
status: Exclude<CrmActivityStatus, 'overdue'>;
priority: CrmActivityPriority;
outcome: string | null;
nextAction: string | null;
createdBy: string;
createdAt: string;
updatedAt: string;
}
export const CRM_ACTIVITY_PERMISSIONS = {
read: PERMISSIONS.crmActivityRead,
create: PERMISSIONS.crmActivityCreate,
update: PERMISSIONS.crmActivityUpdate,
complete: PERMISSIONS.crmActivityComplete,
delete: PERMISSIONS.crmActivityDelete,
auditLogRead: PERMISSIONS.crmAuditLogRead
} as const;
export function resolveCrmActivityStatus(input: {
status: Exclude<CrmActivityStatus, 'overdue'>;
dueDate?: string | null;
completedAt?: string | null;
now?: Date;
}): CrmActivityStatus {
if (input.completedAt || input.status === 'completed' || input.status === 'cancelled') {
return input.status;
}
if (!input.dueDate) {
return input.status;
}
const today = (input.now ?? new Date()).toISOString().slice(0, 10);
return input.dueDate < today ? 'overdue' : input.status;
}
import { PERMISSIONS } from '@/lib/auth/rbac';