Fix UserController permission serialization and include current updates

This commit is contained in:
2026-02-27 14:38:22 -06:00
parent 51eb36f4a6
commit b1f6462ac3
50 changed files with 6150 additions and 30 deletions
@@ -0,0 +1,145 @@
import { Collection } from "@discordjs/collection";
import { connectWiseApi } from "../../../constants";
import {
CWOpportunity,
CWOpportunitySummary,
CWForecastItem,
CWOpportunityNote,
CWOpportunityContact,
} from "./opportunity.types";
export const opportunityCw = {
/**
* Count Opportunities
*
* Returns the total number of opportunities in ConnectWise.
* Optionally accepts CW conditions string for filtered counts.
*/
countItems: async (conditions?: string): Promise<number> => {
const query = conditions
? `/sales/opportunities/count?conditions=${encodeURIComponent(conditions)}`
: "/sales/opportunities/count";
const response = await connectWiseApi.get(query);
return response.data.count;
},
/**
* Fetch All Opportunity Summaries
*
* Lightweight fetch returning only id and _info (for lastUpdated comparison).
* Paginates through all opportunities.
*/
fetchAllSummaries: async (): Promise<
Collection<number, CWOpportunitySummary>
> => {
const allItems = new Collection<number, CWOpportunitySummary>();
const pageSize = 1000;
const count = await opportunityCw.countItems();
const totalPages = Math.ceil(count / pageSize);
for (let page = 0; page < totalPages; page++) {
const response = await connectWiseApi.get(
`/sales/opportunities?page=${page + 1}&pageSize=${pageSize}&fields=id,_info`,
);
const items: CWOpportunitySummary[] = response.data;
for (const item of items) {
allItems.set(item.id, item);
}
}
return allItems;
},
/**
* Fetch All Opportunities (Full)
*
* Fetches all opportunities with complete data. Paginates through
* the full list.
*/
fetchAll: async (
conditions?: string,
): Promise<Collection<number, CWOpportunity>> => {
const allItems = new Collection<number, CWOpportunity>();
const pageSize = 1000;
const count = await opportunityCw.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/opportunities?page=${page + 1}&pageSize=${pageSize}${conditionsParam}`,
);
const items: CWOpportunity[] = response.data;
for (const item of items) {
allItems.set(item.id, item);
}
}
return allItems;
},
/**
* Fetch Single Opportunity
*
* Fetches a single opportunity by its ConnectWise ID.
*/
fetch: async (id: number): Promise<CWOpportunity> => {
const response = await connectWiseApi.get(`/sales/opportunities/${id}`);
return response.data;
},
/**
* Fetch Opportunities by Company
*
* Fetches all opportunities associated with a specific ConnectWise company ID.
*/
fetchByCompany: async (
cwCompanyId: number,
): Promise<Collection<number, CWOpportunity>> => {
return opportunityCw.fetchAll(`company/id=${cwCompanyId}`);
},
/**
* Fetch Opportunity Forecasts
*
* Fetches forecast/revenue items for a given opportunity.
*/
fetchForecasts: async (opportunityId: number): Promise<CWForecastItem[]> => {
const response = await connectWiseApi.get(
`/sales/opportunities/${opportunityId}/forecast`,
);
return response.data;
},
/**
* Fetch Opportunity Notes
*
* Fetches notes associated with a given opportunity.
*/
fetchNotes: async (opportunityId: number): Promise<CWOpportunityNote[]> => {
const response = await connectWiseApi.get(
`/sales/opportunities/${opportunityId}/notes`,
);
return response.data;
},
/**
* Fetch Opportunity Contacts
*
* Fetches contacts associated with a given opportunity.
*/
fetchContacts: async (
opportunityId: number,
): Promise<CWOpportunityContact[]> => {
const response = await connectWiseApi.get(
`/sales/opportunities/${opportunityId}/contacts`,
);
return response.data;
},
};