Files
iistwin/server/storage.ts

487 lines
37 KiB
TypeScript

// Public entry point for the storage layer.
// Implementation is split into domain modules under server/storage/
import { users, organizations, userSessions, invitations, userCustomFields, userCustomValues, forms, formTabs, formFields, formStatuses, statusTransitions, tasks, taskFieldValues, fieldHistory, taskMessages, userNotifications, messageReads, bookmarkFolders, bookmarks, bots, botSubscriptions, botSessions, dataTables, dataTableRows, dataTablePermissions, externalServices, regularTableRows, fieldTemplates, customTabModules, taskTabValues, deviceTokens, userPresence, webPushSubscriptions, customPages, type User, type Organization, type UserSession, type Invitation, type InsertUser, type InsertOrganization, type InsertUserSession, type InsertInvitation, type UserWithOrganization, type UserCustomField, type UserCustomValue, type CreateUserCustomField, type UpdateUserCustomField, type UserProfileTab, type UserProfileField, type UserProfileFieldValue, type UserProfileAuditLog, type InsertUserProfileTab, type InsertUserProfileField, type InsertUserProfileFieldValue, type InsertUserProfileAuditLog, userProfileAuditLog, type Form, type FormTab, type FormField, type FormStatus, type StatusTransition, type Task, type TaskFieldValue, type FieldHistory, type TaskMessage, type TaskMessageWithAuthor, type UserNotification, type MessageRead, type InsertMessageRead, type BookmarkFolder, type Bookmark, type InsertForm, type InsertFormTab, type InsertFormField, type InsertFormStatus, type InsertStatusTransition, type InsertTask, type InsertTaskFieldValue, type InsertFieldHistory, type InsertTaskMessage, type InsertUserNotification, type InsertBookmarkFolder, type InsertBookmark, type Bot, type BotSubscription, type BotSession, type InsertBot, type InsertBotSubscription, type InsertBotSession, type BotWithSubscriptions, type DataTable, type DataTableRow, type DataTablePermission, type DataTableAccessRule, type InsertDataTableAccessRule, type InsertDataTable, type InsertDataTableRow, type InsertDataTablePermission, type DataTableWithRows, type DataTableFull, type ExternalService, type InsertExternalService, type RegularTableRow, type InsertRegularTableRow, type FieldTemplate, type InsertFieldTemplate, type CustomTabModule, type InsertCustomTabModule, type TaskTabValue, type InsertTaskTabValue, type DeviceToken, type InsertDeviceToken, type UserPresence, type InsertUserPresence, type WebPushSubscription, type CustomPage, type InsertCustomPage } from "@shared/schema";
import { organizationApiKeys, type OrganizationApiKey } from "@shared/schema";
import { automations, type Automation, type InsertAutomation } from "@shared/schema";
import { taskRelations, type TaskRelation, type InsertTaskRelation } from "@shared/schema";
import { taskReminders, type TaskReminder, type InsertTaskReminder } from "@shared/schema";
import { ragSettings, type RagSetting, embeddingQueue } from "@shared/schema";
import { llmProviders, type LlmProvider, type InsertLlmProvider } from "@shared/schema";
import { systemConfig } from "@shared/schema";
import { taskAuditLog, type TaskAuditLog, type InsertTaskAuditLog } from "@shared/schema";
import { taskRoles, type TaskRole, taskUserAccess, type TaskUserAccess, roleMembers, roles, taskAssignees, type TaskAssignee } from "@shared/schema";
import { userOfflineSubscriptions, type UserOfflineSubscription, type InsertUserOfflineSubscription } from "@shared/schema";
import { db } from "./db";
import { eq, and, or, desc, asc, exists, isNull, isNotNull, sql, ilike, inArray, lte } from "drizzle-orm";
import { alias } from "drizzle-orm/pg-core";
import crypto from "crypto";
import { formatUserName } from "./utils/formatUserName";
export interface RelatedTreeNode {
id: number;
title: string;
formId: number;
formName: string;
fieldName: string;
isFinal: boolean;
statusName: string | null;
statusColor: string | null;
nodes: RelatedTreeNode[];
}
export interface IStorage {
// Organizations
getOrganization(id: number): Promise<Organization | undefined>;
getOrganizationBySlug(slug: string): Promise<Organization | undefined>;
createOrganization(organization: InsertOrganization): Promise<Organization>;
// Users
getUser(id: number): Promise<User | undefined>;
getUserWithOrganization(id: number): Promise<UserWithOrganization | undefined>;
getUserByEmail(email: string, organizationId?: number): Promise<User | undefined>;
getUserByEmailAndSlug(email: string, slug: string): Promise<UserWithOrganization | undefined>;
getUsersByOrganization(organizationId: number): Promise<User[]>;
listUsers(organizationId: number, options?: import('./storage/users.storage').ListUsersOptions): Promise<import('./storage/users.storage').ListUsersResult>;
getLinkedTasksForUser(userId: number, organizationId: number): Promise<
Array<{
task: Task;
form: { id: number; name: string };
status: FormStatus | null;
field: FormField;
}>
>;
getUserByResetPasswordToken(token: string): Promise<User | undefined>;
createUser(insertUser: InsertUser): Promise<User>;
updateUser(id: number, updates: Partial<User>): Promise<User>;
deleteUser(id: number): Promise<void>;
// User offline subscriptions
getUserOfflineSubscriptions(userId: number, organizationId: number): Promise<UserOfflineSubscription[]>;
getUserOfflineSubscription(userId: number, formId: number): Promise<UserOfflineSubscription | undefined>;
upsertUserOfflineSubscription(subscription: InsertUserOfflineSubscription): Promise<UserOfflineSubscription>;
deleteUserOfflineSubscription(userId: number, formId: number): Promise<void>;
// User sessions
createUserSession(session: InsertUserSession): Promise<UserSession>;
getUserSessionByToken(refreshToken: string): Promise<UserSession | undefined>;
getUserSessionByParentToken(parentRefreshToken: string): Promise<UserSession | undefined>;
getActiveSessionInFamily(familyId: string): Promise<UserSession | undefined>;
markSessionReplaced(refreshToken: string, replacedByToken: string): Promise<void>;
revokeSession(refreshToken: string): Promise<void>;
revokeSessionFamily(familyId: string): Promise<void>;
revokeAllUserSessions(userId: number): Promise<void>;
deleteUserSession(refreshToken: string): Promise<void>;
deleteUserSessions(userId: number): Promise<void>;
// Invitations
createInvitation(invitation: InsertInvitation): Promise<Invitation>;
getInvitationByToken(token: string): Promise<Invitation | undefined>;
getInvitationsByOrganization(organizationId: number): Promise<Invitation[]>;
markInvitationAsUsed(token: string): Promise<Invitation>;
deleteInvitation(id: number, organizationId: number): Promise<void>;
// User Custom Fields
getUserCustomFields(organizationId: number): Promise<UserCustomField[]>;
getUserCustomField(id: number, organizationId: number): Promise<UserCustomField | undefined>;
createUserCustomField(organizationId: number, field: CreateUserCustomField): Promise<UserCustomField>;
updateUserCustomField(id: number, organizationId: number, updates: UpdateUserCustomField): Promise<UserCustomField>;
deleteUserCustomField(id: number, organizationId: number): Promise<void>;
reorderUserCustomFields(organizationId: number, fieldIds: number[]): Promise<void>;
// User Custom Values
getUserCustomValues(userId: number, organizationId: number): Promise<UserCustomValue[]>;
setUserCustomValue(userId: number, fieldId: number, value: string | null, organizationId: number): Promise<UserCustomValue>;
setUserCustomValues(userId: number, values: Array<{ fieldId: number; value: string | null }>, organizationId: number): Promise<void>;
// User Profile Tabs
getUserProfileTabs(organizationId: number): Promise<UserProfileTab[]>;
getUserProfileTabsByCreationOrder(organizationId: number): Promise<UserProfileTab[]>;
bulkSaveUserProfileTabs(organizationId: number, tabs: Array<{ id?: number; name: string; code: string; position?: number; displayOrder?: number }>): Promise<UserProfileTab[]>;
// User Profile Fields
getUserProfileFields(organizationId: number): Promise<UserProfileField[]>;
getUserProfileFieldsByCreationOrder(organizationId: number): Promise<UserProfileField[]>;
getUserProfileFieldById(id: number, organizationId: number): Promise<UserProfileField | undefined>;
bulkSaveUserProfileFields(organizationId: number, fieldIdsToDelete: number[], fields: Array<{ id?: number; name: string; code: string; type: string; isRequired?: boolean; placeholder?: string | null; defaultValue?: string | null; validationRules?: unknown; options?: unknown; position?: number | null; displayOrder?: number | null; tabId?: number | null; linkedFormId?: number | null; companyAutofill?: unknown; maxFileCount?: number | null; maxFileSizeMB?: number | null; autoProlongation?: boolean | null; autoProlongationLabel?: string | null }>): Promise<UserProfileField[]>;
// User Profile Field Values
getUserProfileFieldValues(userId: number): Promise<UserProfileFieldValue[]>;
getUserProfileFieldValue(userId: number, fieldId: number): Promise<UserProfileFieldValue | undefined>;
createUserProfileFieldValue(insertValue: InsertUserProfileFieldValue): Promise<UserProfileFieldValue>;
createUserProfileFieldValueWithAudit(insertValue: InsertUserProfileFieldValue, organizationId: number, changedBy: number): Promise<UserProfileFieldValue>;
updateUserProfileFieldValue(userId: number, fieldId: number, updates: Partial<UserProfileFieldValue>): Promise<UserProfileFieldValue>;
updateUserProfileFieldValueWithAudit(userId: number, fieldId: number, updates: Partial<UserProfileFieldValue>, organizationId: number, changedBy: number): Promise<UserProfileFieldValue>;
deleteUserProfileFieldValue(userId: number, fieldId: number): Promise<void>;
deleteUserProfileFieldValueWithAudit(userId: number, fieldId: number, organizationId: number, changedBy: number): Promise<void>;
getUserProfileDetail(userId: number, organizationId: number): Promise<{ user: any; tabs: UserProfileTab[]; fields: UserProfileField[]; fieldValues: UserProfileFieldValue[] }>;
// User Profile Audit Log
getUserProfileAuditLog(userId: number, organizationId: number): Promise<UserProfileAuditLog[]>;
createUserProfileAuditLog(insertValue: InsertUserProfileAuditLog): Promise<UserProfileAuditLog>;
// Forms
getForm(id: number, organizationId: number): Promise<Form | undefined>;
getFormsByOrganization(organizationId: number): Promise<Form[]>;
createForm(insertForm: InsertForm): Promise<Form>;
updateForm(id: number, organizationId: number, updates: Partial<Form>): Promise<Form>;
deleteForm(id: number, organizationId: number): Promise<void>;
getTasksCountByForm(formId: number): Promise<{ total: number; active: number; completed: number }>;
getTaskCountsByStatus(formId: number, organizationId: number): Promise<Array<{ statusId: number; name: string; color: string; count: number }>>;
getFormsWithOfflineCache(organizationId: number): Promise<Form[]>;
getOfflineCacheConfig(id: number, organizationId: number): Promise<Form['offlineCache']>;
updateFormOfflineCache(id: number, organizationId: number, config: Form['offlineCache']): Promise<Form>;
// Form Tabs
getFormTabs(formId: number, organizationId: number): Promise<FormTab[]>;
getFormTabsByCreationOrder(formId: number, organizationId: number): Promise<FormTab[]>;
getFormTab(id: number, formId: number, organizationId: number): Promise<FormTab | undefined>;
createFormTab(insertTab: InsertFormTab): Promise<FormTab>;
updateFormTab(id: number, formId: number, organizationId: number, updates: Partial<FormTab>): Promise<FormTab>;
deleteFormTab(id: number, formId: number, organizationId: number): Promise<void>;
bulkSaveFormTabs(formId: number, organizationId: number, tabs: Array<{ id?: number; name: string; code: string; type: string; tableColumns?: unknown }>): Promise<FormTab[]>;
// Form Fields
getFormFields(formId: number, organizationId: number): Promise<FormField[]>;
getFormFieldsByCreationOrder(formId: number, organizationId: number): Promise<FormField[]>;
getFormFieldById(id: number, organizationId: number): Promise<FormField | undefined>;
createFormField(insertField: InsertFormField): Promise<FormField>;
updateFormField(id: number, formId: number, organizationId: number, updates: Partial<FormField>): Promise<FormField>;
deleteFormField(id: number, formId: number, organizationId: number): Promise<void>;
bulkSaveFormFields(formId: number, organizationId: number, fieldIdsToDelete: number[], fields: Array<{ id?: number; name: string; code: string; type: string; isRequired?: boolean; placeholder?: string | null; defaultValue?: string | null; validationRules?: unknown; options?: unknown; tabId?: number | null; linkedFormId?: number | null; taskRelationType?: string | null; companyAutofill?: unknown; maxFileCount?: number | null; maxFileSizeMB?: number | null; linkToUserProfile?: boolean | null }>): Promise<FormField[]>;
// Form Statuses
getFormStatuses(formId: number, organizationId: number): Promise<FormStatus[]>;
createFormStatus(insertStatus: InsertFormStatus): Promise<FormStatus>;
updateFormStatus(id: number, formId: number, organizationId: number, updates: Partial<FormStatus>): Promise<FormStatus>;
deleteFormStatus(id: number, formId: number, organizationId: number): Promise<void>;
bulkSaveFormStatuses(formId: number, organizationId: number, statusIdsToDelete: number[], statuses: Array<{ id?: number; name: string; color?: string; isInitial?: boolean; isFinal?: boolean }>): Promise<FormStatus[]>;
// Status Transitions
getStatusTransitions(formId: number, organizationId: number): Promise<StatusTransition[]>;
createStatusTransition(insertTransition: InsertStatusTransition): Promise<StatusTransition>;
updateStatusTransition(id: number, formId: number, organizationId: number, updates: Partial<StatusTransition>): Promise<StatusTransition>;
deleteStatusTransition(id: number, formId: number, organizationId: number): Promise<void>;
// Tasks
getTask(id: number, organizationId: number): Promise<Task | undefined>;
getTaskDetail(id: number, organizationId: number): Promise<{
task: Task;
form: Form;
fields: FormField[];
statuses: FormStatus[];
tabs: FormTab[];
transitions: StatusTransition[];
fieldValues: TaskFieldValue[];
subtasks: Task[];
messages: TaskMessageWithAuthor[];
users: User[];
hasRelations: boolean;
assignees: Array<TaskAssignee & { user: { id: number; firstName: string | null; lastName: string | null; email: string } }>;
} | null>;
getTasksByForm(formId: number, organizationId: number): Promise<Task[]>;
getTasksWithFieldsByForm(formId: number, organizationId: number): Promise<Task[]>;
getTasksWithFieldsByFormOptimized(formId: number, organizationId: number, options?: { limit?: number; offset?: number; assignedTo?: number }): Promise<{ tasks: Task[]; total: number }>;
getTasksByOrganization(organizationId: number, options?: {
limit?: number;
offset?: number;
sortBy?: 'updatedAt' | 'createdAt';
order?: 'asc' | 'desc';
statusId?: number;
assignedTo?: number;
minimal?: boolean;
}): Promise<Task[] | Partial<Task>[]>;
createTask(insertTask: InsertTask): Promise<Task>;
updateTask(id: number, organizationId: number, updates: Partial<Task>): Promise<Task>;
updateTaskIfNotModified(id: number, organizationId: number, updates: Partial<Task>, requiredUpdatedAt: Date): Promise<Task | null>;
deleteTask(id: number, organizationId: number): Promise<void>;
searchTasksByKeyword(organizationId: number, query: string, limit?: number): Promise<Pick<Task, 'id' | 'title' | 'description' | 'formId' | 'currentStatusId'>[]>;
// Task Field Values
getTaskFieldValues(taskId: number, organizationId: number): Promise<TaskFieldValue[]>;
createTaskFieldValue(insertValue: InsertTaskFieldValue): Promise<TaskFieldValue>;
updateTaskFieldValue(taskId: number, fieldId: number, organizationId: number, updates: Partial<TaskFieldValue>): Promise<TaskFieldValue>;
bulkUpsertTaskFieldValues(taskId: number, formId: number, updates: Array<{ fieldId: number; value: unknown }>): Promise<TaskFieldValue[]>;
deleteTaskFieldValue(taskId: number, fieldId: number, organizationId: number): Promise<void>;
// Field History
getFieldHistory(taskId: number, fieldId: number, organizationId: number): Promise<FieldHistory[]>;
createFieldHistory(insertHistory: InsertFieldHistory): Promise<FieldHistory>;
// Task Messages (Chat)
getTaskMessages(taskId: number, organizationId: number): Promise<TaskMessageWithAuthor[]>;
getTaskMessage(messageId: number, organizationId: number): Promise<TaskMessageWithAuthor | undefined>;
createTaskMessage(insertMessage: any, organizationId: number): Promise<any>;
updateTaskMessage(id: number, organizationId: number, updates: Partial<TaskMessage>): Promise<TaskMessage>;
deleteTaskMessage(id: number, organizationId: number): Promise<void>;
// Message Reads (Read Receipts)
markMessageAsRead(messageId: number, userId: number, organizationId: number): Promise<MessageRead>;
getMessageReads(messageId: number, organizationId: number): Promise<MessageRead[]>;
getMessageReadsByUser(userId: number, organizationId: number): Promise<MessageRead[]>;
isMessageReadByUser(messageId: number, userId: number, organizationId: number): Promise<boolean>;
// Bookmark Folders
getBookmarkFolder(id: number, organizationId: number, userId: number): Promise<BookmarkFolder | undefined>;
getBookmarkFoldersByOrganization(organizationId: number, userId: number): Promise<BookmarkFolder[]>;
getBookmarkFoldersByParent(parentId: number | null, organizationId: number, userId: number): Promise<BookmarkFolder[]>;
createBookmarkFolder(insertFolder: InsertBookmarkFolder): Promise<BookmarkFolder>;
updateBookmarkFolder(id: number, organizationId: number, updates: Partial<BookmarkFolder>, userId: number): Promise<BookmarkFolder>;
deleteBookmarkFolder(id: number, organizationId: number, userId: number): Promise<void>;
normalizeBookmarkFolderPositions(organizationId: number, userId: number): Promise<void>;
batchUpdateBookmarkFolderPositions(items: { id: number; position: number }[], organizationId: number, userId: number): Promise<void>;
// Bookmarks
getBookmark(id: number, organizationId: number, userId: number): Promise<Bookmark | undefined>;
getBookmarksByFolder(folderId: number | null, organizationId: number, userId: number): Promise<Bookmark[]>;
getBookmarksByOrganization(organizationId: number, userId: number): Promise<Bookmark[]>;
createBookmark(insertBookmark: InsertBookmark): Promise<Bookmark>;
updateBookmark(id: number, organizationId: number, updates: Partial<Bookmark>, userId: number): Promise<Bookmark>;
deleteBookmark(id: number, organizationId: number, userId: number): Promise<void>;
normalizeBookmarkPositions(organizationId: number, userId: number): Promise<void>;
batchUpdateBookmarkPositions(items: { id: number; position: number }[], organizationId: number, userId: number): Promise<void>;
// User Notifications
getUserNotifications(userId: number, organizationId: number, isRead?: boolean): Promise<UserNotification[]>;
createUserNotification(insertNotification: InsertUserNotification): Promise<UserNotification>;
markNotificationAsRead(id: number, userId: number, organizationId: number): Promise<UserNotification>;
markAllNotificationsAsRead(userId: number, organizationId: number): Promise<void>;
markTaskNotificationsAsRead(taskId: number, userId: number, organizationId: number): Promise<void>;
deleteNotification(id: number, userId: number, organizationId: number): Promise<void>;
// User Search
searchUsers(query: string, organizationId: number, limit?: number): Promise<User[]>;
// Bots
getBot(id: number, organizationId: number): Promise<Bot | undefined>;
getBotByLogin(login: string, organizationId: number): Promise<Bot | undefined>;
getBotsByOrganization(organizationId: number): Promise<Bot[]>;
getBotWithSubscriptions(id: number, organizationId: number): Promise<BotWithSubscriptions | undefined>;
searchBots(query: string, organizationId: number, limit?: number): Promise<Bot[]>;
createBot(insertBot: InsertBot): Promise<Bot>;
updateBot(id: number, organizationId: number, updates: Partial<Bot>): Promise<Bot>;
deleteBot(id: number, organizationId: number): Promise<void>;
// Bot Subscriptions
getBotSubscriptions(botId: number, organizationId: number): Promise<BotSubscription[]>;
getBotSubscriptionsByForm(formId: number, organizationId: number): Promise<BotSubscription[]>;
getBotSubscriptionsByStatus(statusId: number, organizationId: number): Promise<BotSubscription[]>;
getBotSubscriptionsByTransition(transitionId: number, organizationId: number): Promise<BotSubscription[]>;
createBotSubscription(insertSubscription: InsertBotSubscription): Promise<BotSubscription>;
updateBotSubscription(id: number, organizationId: number, updates: Partial<BotSubscription>): Promise<BotSubscription>;
deleteBotSubscription(id: number, organizationId: number): Promise<void>;
// Bot Sessions
createBotSession(session: InsertBotSession): Promise<BotSession>;
getBotSessionByToken(refreshToken: string): Promise<BotSession | undefined>;
deleteBotSession(refreshToken: string): Promise<void>;
deleteBotSessions(botId: number): Promise<void>;
// Data Tables
getDataTable(id: number, organizationId: number): Promise<DataTable | undefined>;
getDataTablesByOrganization(organizationId: number): Promise<DataTable[]>;
getDataTablesWithAccess(userId: number, organizationId: number): Promise<DataTable[]>;
getDataTableFull(id: number, organizationId: number): Promise<DataTableFull | undefined>;
createDataTable(table: InsertDataTable & { organizationId: number; createdBy: number }): Promise<DataTable>;
updateDataTable(id: number, organizationId: number, updates: Partial<DataTable>): Promise<DataTable>;
deleteDataTable(id: number, organizationId: number): Promise<void>;
// Data Table Rows
getDataTableRows(tableId: number, organizationId: number): Promise<DataTableRow[]>;
getDataTableRow(id: number, tableId: number, organizationId: number): Promise<DataTableRow | undefined>;
createDataTableRow(row: InsertDataTableRow): Promise<DataTableRow>;
updateDataTableRow(id: number, tableId: number, organizationId: number, updates: Partial<DataTableRow>): Promise<DataTableRow>;
deleteDataTableRow(id: number, tableId: number, organizationId: number): Promise<void>;
bulkCreateDataTableRows(tableId: number, rows: { values: string[] }[]): Promise<DataTableRow[]>;
bulkDeleteDataTableRows(tableId: number, organizationId: number): Promise<void>;
applyDataTableSync(tableId: number, deleted: { id: number }[], added: { values: string[]; position: number }[], reordered: { id: number; newPosition: number }[], positionUpdates: { id: number; position: number }[]): Promise<void>;
applyDataTableDiff(tableId: number, upsertRows: { values: string[] }[], deleteKeys: string[], currentRows: DataTableRow[]): Promise<{ added: DataTableRow[]; updated: DataTableRow[]; deleted: DataTableRow[] }>;
// Data Table Permissions
getDataTablePermissions(tableId: number, organizationId: number): Promise<(DataTablePermission & { user: { id: number; firstName: string; lastName: string; email: string } })[]>;
getDataTablePermission(tableId: number, userId: number): Promise<DataTablePermission | undefined>;
getUserTableRole(tableId: number, userId: number, createdBy: number, organizationId?: number): Promise<'admin' | 'editor' | 'reader' | null>;
setDataTablePermission(permission: InsertDataTablePermission): Promise<DataTablePermission>;
deleteDataTablePermission(tableId: number, userId: number): Promise<void>;
// Data Table Access Rules
getDataTableAccessRules(tableId: number, organizationId: number): Promise<DataTableAccessRule[]>;
createDataTableAccessRule(data: InsertDataTableAccessRule): Promise<DataTableAccessRule>;
deleteDataTableAccessRule(id: number, organizationId: number): Promise<void>;
getLinkedFormsForTable(tableId: number, organizationId: number): Promise<{ id: number; name: string }[]>;
// External Services
getExternalServices(organizationId: number): Promise<ExternalService[]>;
getExternalService(id: number, organizationId: number): Promise<ExternalService | undefined>;
getExternalServiceByType(serviceType: string, organizationId: number): Promise<ExternalService | undefined>;
createExternalService(service: InsertExternalService): Promise<ExternalService>;
updateExternalService(id: number, organizationId: number, updates: Partial<ExternalService>): Promise<ExternalService>;
deleteExternalService(id: number, organizationId: number): Promise<void>;
// Regular Table Rows (for type='table' tabs)
getRegularTableRows(taskId: number, tabId: number): Promise<RegularTableRow[]>;
getRegularTableRow(id: number, taskId: number, tabId: number): Promise<RegularTableRow | undefined>;
createRegularTableRow(row: InsertRegularTableRow): Promise<RegularTableRow>;
updateRegularTableRow(id: number, taskId: number, tabId: number, updates: Partial<RegularTableRow>): Promise<RegularTableRow>;
deleteRegularTableRow(id: number, taskId: number, tabId: number): Promise<void>;
// Field Templates
getFieldTemplates(organizationId: number): Promise<FieldTemplate[]>;
getFieldTemplate(id: number, organizationId: number): Promise<FieldTemplate | undefined>;
getFieldTemplateByCode(code: string, organizationId: number): Promise<FieldTemplate | undefined>;
createFieldTemplate(field: InsertFieldTemplate): Promise<FieldTemplate>;
updateFieldTemplate(id: number, organizationId: number, updates: Partial<FieldTemplate>): Promise<FieldTemplate>;
deleteFieldTemplate(id: number, organizationId: number): Promise<void>;
// Custom Tab Modules
getCustomTabModules(organizationId: number): Promise<CustomTabModule[]>;
getCustomTabModule(id: number, organizationId: number): Promise<CustomTabModule | undefined>;
getCustomTabModuleByType(type: string, organizationId: number): Promise<CustomTabModule | undefined>;
createCustomTabModule(module: InsertCustomTabModule): Promise<CustomTabModule>;
updateCustomTabModule(id: number, organizationId: number, updates: Partial<CustomTabModule>): Promise<CustomTabModule>;
deleteCustomTabModule(id: number, organizationId: number): Promise<void>;
getFormIdsByTabModuleType(type: string, organizationId: number): Promise<number[]>;
getFormTabByModuleType(formId: number, type: string, organizationId: number): Promise<FormTab | undefined>;
// Custom JS Pages
getCustomPages(organizationId: number): Promise<CustomPage[]>;
getCustomPage(id: number, organizationId: number): Promise<CustomPage | undefined>;
getCustomPageBySlug(slug: string, organizationId: number): Promise<CustomPage | undefined>;
createCustomPage(page: InsertCustomPage): Promise<CustomPage>;
updateCustomPage(id: number, organizationId: number, updates: Partial<InsertCustomPage>): Promise<CustomPage>;
deleteCustomPage(id: number, organizationId: number): Promise<void>;
// Automations
getAutomations(organizationId: number): Promise<Automation[]>;
getOfflineAutomations(organizationId: number): Promise<Automation[]>;
getAutomation(id: number, organizationId: number): Promise<Automation | undefined>;
createAutomation(automation: InsertAutomation): Promise<Automation>;
updateAutomation(id: number, organizationId: number, updates: Partial<InsertAutomation>): Promise<Automation>;
deleteAutomation(id: number, organizationId: number): Promise<void>;
// Task Tab Values (per-task data for custom modules)
getTaskTabValues(taskId: number, tabId: number): Promise<TaskTabValue | undefined>;
getTaskTabValuesByTask(taskId: number): Promise<TaskTabValue[]>;
upsertTaskTabValues(taskId: number, tabId: number, values: Record<string, any>): Promise<TaskTabValue>;
// Organization API Keys (MCP)
createApiKey(organizationId: number, createdBy: number, label: string): Promise<{ key: string; record: OrganizationApiKey }>;
listApiKeys(organizationId: number): Promise<OrganizationApiKey[]>;
deleteApiKey(id: number, organizationId: number): Promise<void>;
getApiKeyByHash(rawKey: string): Promise<OrganizationApiKey | undefined>;
getApiKeyByLegacyHash(rawKey: string): Promise<OrganizationApiKey | undefined>;
touchApiKey(id: number): Promise<void>;
// Task Relations
upsertTaskRelation(data: { parentTaskId: number; childTaskId: number; fieldId?: number | null; organizationId: number }): Promise<TaskRelation>;
// Task Roles
getTaskRoles(taskId: number, organizationId: number): Promise<Array<TaskRole & { role: { id: number; name: string; parentId: number | null } }>>;
addTaskRole(taskId: number, roleId: number, organizationId: number): Promise<TaskRole>;
removeTaskRole(taskId: number, roleId: number, organizationId: number): Promise<void>;
// Task Assignees (multiple users)
getTaskAssignees(taskId: number, organizationId: number): Promise<Array<TaskAssignee & { user: { id: number; firstName: string | null; lastName: string | null; email: string } }>>;
addTaskAssignee(taskId: number, userId: number, organizationId: number): Promise<TaskAssignee>;
removeTaskAssignee(taskId: number, userId: number, organizationId: number): Promise<void>;
// Task User Access
getTaskUserAccess(taskId: number, organizationId: number): Promise<Array<TaskUserAccess & { user: { id: number; firstName: string | null; lastName: string | null; email: string } }>>;
recordTaskInteraction(taskId: number, userId: number, organizationId: number, grantedVia: string, roleId?: number | null): Promise<void>;
recordTaskInteractionAuto(taskId: number, userId: number, organizationId: number): Promise<void>;
upsertTaskUserAccess(taskId: number, userId: number, organizationId: number, grantedVia: string): Promise<void>;
recordTransitionAccess(taskId: number, userId: number, organizationId: number, roleId: number | null, statusId: number): Promise<void>;
revokeTaskUserAccess(taskId: number, userId: number, organizationId: number): Promise<void>;
canUserAccessTask(taskId: number, userId: number, organizationId: number, appRole: string): Promise<boolean>;
getAccessibleTaskIds(userId: number, organizationId: number, appRole: string): Promise<Set<number> | null>;
resolveTaskAccessGrant(taskId: number, userId: number, organizationId: number): Promise<{ grantedVia: string; roleId: number | null }>;
// Form Access Rules
getFormAccessRules(formId: number, organizationId: number): Promise<import('@shared/schema').FormAccessRule[]>;
createFormAccessRule(data: import('@shared/schema').InsertFormAccessRule): Promise<import('@shared/schema').FormAccessRule>;
updateFormAccessRule(id: number, organizationId: number, updates: Partial<Pick<import('@shared/schema').FormAccessRule, 'accessLevel'>>): Promise<import('@shared/schema').FormAccessRule>;
deleteFormAccessRule(id: number, organizationId: number): Promise<void>;
transferFormOwnership(formId: number, organizationId: number, newAuthorId: number): Promise<void>;
canUserAccessForm(userId: number, formId: number, organizationId: number, requiredLevel?: 'participate' | 'view_all' | 'admin'): Promise<boolean>;
deleteTaskRelationByField(fieldId: number, taskId: number, organizationId: number): Promise<void>;
getTaskRelations(taskId: number, organizationId: number): Promise<TaskRelation[]>;
// Task Reminders
getTaskReminders(taskId: number, organizationId: number): Promise<TaskReminder[]>;
createTaskReminder(data: InsertTaskReminder): Promise<TaskReminder>;
deleteTaskReminder(id: number, organizationId: number): Promise<void>;
getDueReminders(): Promise<TaskReminder[]>;
markReminderSent(id: number): Promise<void>;
getUsersByRole(role: string, organizationId: number): Promise<User[]>;
getUsersByOrgRoleId(roleId: number, organizationId: number): Promise<User[]>;
// Task Audit Log
addTaskAuditLog(entry: InsertTaskAuditLog): Promise<TaskAuditLog>;
getTaskAuditLog(taskId: number, organizationId: number): Promise<TaskAuditLog[]>;
// Roles
getRoles(organizationId: number): Promise<(import('@shared/schema').Role & { memberCount: number; members: { id: number; userId: number; user: { id: number; firstName: string; lastName: string; email: string } }[]; manager: { id: number; firstName: string; lastName: string; middleName: string | null; email: string } | null })[]>;
getRole(id: number, organizationId: number): Promise<import('@shared/schema').Role | undefined>;
createRole(data: { organizationId: number; name: string; description?: string | null; parentId?: number | null; managerId?: number | null }): Promise<import('@shared/schema').Role>;
updateRole(id: number, organizationId: number, updates: { name?: string; description?: string | null; parentId?: number | null; managerId?: number | null }): Promise<import('@shared/schema').Role>;
deleteRole(id: number, organizationId: number): Promise<void>;
getRoleMembers(roleId: number, organizationId: number): Promise<(import('@shared/schema').Role & { members: { id: number; userId: number; user: { id: number; firstName: string; lastName: string; email: string } }[]; manager: { id: number; firstName: string; lastName: string; middleName: string | null; email: string } | null })>;
addRoleMember(roleId: number, userId: number, organizationId: number): Promise<void>;
removeRoleMember(roleId: number, userId: number, organizationId: number): Promise<void>;
getRoleMembersByRole(roleId: number): Promise<{ id: number; userId: number; createdAt: Date | null }[]>;
getUserRoles(userId: number, organizationId: number): Promise<import('@shared/schema').Role[]>;
// Super Admins
getSuperAdminByEmail(email: string): Promise<import('@shared/schema').SuperAdmin | undefined>;
getSuperAdminById(id: number): Promise<import('@shared/schema').SuperAdmin | undefined>;
getAllSuperAdmins(): Promise<import('@shared/schema').SuperAdmin[]>;
createSuperAdmin(data: import('@shared/schema').InsertSuperAdmin): Promise<import('@shared/schema').SuperAdmin>;
deleteSuperAdmin(id: number): Promise<void>;
getSuperAdminCount(): Promise<number>;
updateSuperAdminLastLogin(id: number): Promise<void>;
updateSuperAdminPassword(id: number, passwordHash: string): Promise<void>;
getAllOrganizationsWithStats(): Promise<Array<import('@shared/schema').Organization & { totalUsers: number; activeUsers: number; totalTasks: number; lastActivity: Date | null; billingBalance: string; billingCurrency: string }>>;
updateOrganization(id: number, updates: Partial<import('@shared/schema').Organization>): Promise<import('@shared/schema').Organization>;
getOrganizationDetailedStats(organizationId: number): Promise<{ forms: number; tasks: number; totalUsers: number; activeUsers: number; lastActivity: Date | null }>;
// Billing
getBillingSettings(organizationId: number): Promise<import('@shared/schema').OrganizationBilling | null>;
getOrCreateBillingSettings(organizationId: number): Promise<import('@shared/schema').OrganizationBilling>;
updateBillingSettings(organizationId: number, updates: Partial<import('@shared/schema').OrganizationBilling>): Promise<import('@shared/schema').OrganizationBilling>;
addBillingCredit(organizationId: number, amount: number, description: string, createdBy?: number): Promise<import('@shared/schema').BillingTransaction>;
getBillingTransactions(organizationId: number, limit?: number): Promise<import('@shared/schema').BillingTransaction[]>;
setBillingBlocked(organizationId: number, blocked: boolean): Promise<void>;
getBillingSummary(organizationId: number): Promise<{ balance: string; pricePerUser: string; currency: string; nextBillingDate: string | null; billingBlocked: boolean; activeUsers: number; estimatedCharge: string }>;
processBillingCycle(): Promise<void>;
// RAG Settings
getRagSettings(organizationId: number): Promise<RagSetting | undefined>;
upsertRagSettings(organizationId: number, updates: Partial<Omit<RagSetting, 'organizationId' | 'updatedAt'>>): Promise<RagSetting>;
// Embedding Queue
enqueueEmbedding(organizationId: number, entityType: 'form' | 'task' | 'task_message', entityId: number, operation?: 'upsert' | 'delete'): Promise<void>;
getPendingEmbeddingQueue(limit?: number): Promise<Array<{ id: number; organizationId: number; entityType: 'form' | 'task' | 'task_message'; entityId: number; operation: 'upsert' | 'delete' }>>;
markEmbeddingQueueProcessed(ids: number[]): Promise<void>;
clearEmbeddingQueue(): Promise<void>;
// LLM Providers
getLlmProviders(organizationId: number): Promise<LlmProvider[]>;
getLlmProvider(id: number, organizationId: number): Promise<LlmProvider | undefined>;
createLlmProvider(data: InsertLlmProvider): Promise<LlmProvider>;
updateLlmProvider(id: number, organizationId: number, updates: Partial<Omit<LlmProvider, 'id' | 'organizationId' | 'createdAt'>>): Promise<LlmProvider>;
deleteLlmProvider(id: number, organizationId: number): Promise<void>;
// System Config
getSystemConfig(key: string): Promise<string | null>;
setSystemConfig(key: string, value: string): Promise<void>;
// Web Push
registerWebPushSubscription(userId: number, organizationId: number, endpoint: string, subscription: string): Promise<void>;
unregisterWebPushSubscription(endpoint: string): Promise<void>;
getWebPushSubscriptions(userId: number, organizationId: number): Promise<any[]>;
getWebPushSubscriptionsByOrganization(organizationId: number): Promise<any[]>;
clearAllWebPushSubscriptions(): Promise<number>;
}
export { DatabaseStorage, storage } from "./storage/index";