import { Collection } from "@discordjs/collection"; import { connectWiseApi } from "../../../constants"; import { CWActivity, CWActivitySummary, CWCreateActivity, CWPatchOperation, } from "./activity.types"; export const activityCw = { /** * Count Activities * * Returns the total number of activities in ConnectWise. * Optionally accepts CW conditions string for filtered counts. */ countItems: async (conditions?: string): Promise => { const query = conditions ? `/sales/activities/count?conditions=${encodeURIComponent(conditions)}` : "/sales/activities/count"; const response = await connectWiseApi.get(query); return response.data.count; }, /** * Fetch All Activity Summaries * * Lightweight fetch returning only id and _info (for lastUpdated comparison). * Paginates through all activities. */ fetchAllSummaries: async (): Promise< Collection > => { const allItems = new Collection(); const pageSize = 1000; const count = await activityCw.countItems(); const totalPages = Math.ceil(count / pageSize); for (let page = 0; page < totalPages; page++) { const response = await connectWiseApi.get( `/sales/activities?page=${page + 1}&pageSize=${pageSize}&fields=id,_info`, ); const items: CWActivitySummary[] = response.data; for (const item of items) { allItems.set(item.id, item); } } return allItems; }, /** * Fetch All Activities (Full) * * Fetches all activities with complete data. Paginates through * the full list. Optionally accepts CW conditions string for filtering. */ fetchAll: async ( conditions?: string, ): Promise> => { const allItems = new Collection(); const pageSize = 1000; const count = await activityCw.countItems(conditions); const totalPages = Math.ceil(count / pageSize); for (let page = 0; page < totalPages; page++) { const conditionsParam = conditions ? `&conditions=${encodeURIComponent(conditions)}` : ""; const response = await connectWiseApi.get( `/sales/activities?page=${page + 1}&pageSize=${pageSize}${conditionsParam}`, ); const items: CWActivity[] = response.data; for (const item of items) { allItems.set(item.id, item); } } return allItems; }, /** * Fetch Single Activity * * Fetches a single activity by its ConnectWise ID. */ fetch: async (id: number): Promise => { const response = await connectWiseApi.get(`/sales/activities/${id}`); return response.data; }, /** * Fetch Activities by Company * * Fetches all activities associated with a specific ConnectWise company ID. */ fetchByCompany: async ( cwCompanyId: number, ): Promise> => { return activityCw.fetchAll(`company/id=${cwCompanyId}`); }, /** * Fetch Activities by Opportunity * * Fetches all activities associated with a specific opportunity ID. */ fetchByOpportunity: async ( opportunityId: number, ): Promise> => { return activityCw.fetchAll(`opportunity/id=${opportunityId}`); }, /** * Fetch Activities by Opportunity (Direct) * * Lightweight single-call variant that skips the count request. * Fetches up to 1000 activities in a single GET — sufficient for * virtually all opportunities. Used by the background cache refresh * to avoid doubling CW API calls. */ fetchByOpportunityDirect: async ( opportunityId: number, ): Promise => { const conditions = encodeURIComponent(`opportunity/id=${opportunityId}`); const response = await connectWiseApi.get( `/sales/activities?pageSize=1000&conditions=${conditions}`, ); return response.data; }, /** * Create Activity * * Creates a new activity in ConnectWise. */ create: async (activity: CWCreateActivity): Promise => { const response = await connectWiseApi.post("/sales/activities", activity); return response.data; }, /** * Update Activity (PATCH) * * Updates an existing activity using JSON Patch operations. */ update: async ( id: number, operations: CWPatchOperation[], ): Promise => { const response = await connectWiseApi.patch( `/sales/activities/${id}`, operations, ); return response.data; }, /** * Replace Activity (PUT) * * Replaces an entire activity record in ConnectWise. */ replace: async ( id: number, activity: CWCreateActivity, ): Promise => { const response = await connectWiseApi.put( `/sales/activities/${id}`, activity, ); return response.data; }, /** * Delete Activity * * Deletes an activity by its ConnectWise ID. */ delete: async (id: number): Promise => { await connectWiseApi.delete(`/sales/activities/${id}`); }, };