205 lines
6.3 KiB
TypeScript
205 lines
6.3 KiB
TypeScript
import { Company } from "../../generated/prisma/client";
|
|
import { connectWiseApi } from "../constants";
|
|
import { fetchCwCompanyById } from "../modules/cw-utils/fetchCompany";
|
|
import { fetchCompanyConfigurations } from "../modules/cw-utils/configurations/fetchCompanyConfigurations";
|
|
import { updateCwInternalCompany } from "../modules/cw-utils/updateCompany";
|
|
import {
|
|
fetchCompanySites,
|
|
fetchCompanySite,
|
|
serializeCwSite,
|
|
} from "../modules/cw-utils/sites/companySites";
|
|
import { Company as CWCompany, Contact } from "../types/ConnectWiseTypes";
|
|
|
|
/**
|
|
* Company Controller
|
|
*
|
|
* This class is for creating a controller that can manage company data,
|
|
* synchronize with external systems, and provide methods for accessing
|
|
* and updating company information within our internal system.
|
|
*/
|
|
export class CompanyController {
|
|
public readonly id: string;
|
|
public name: string;
|
|
public readonly cw_Identifier: string;
|
|
public readonly cw_CompanyId: number;
|
|
public cw_Data?: {
|
|
company: CWCompany;
|
|
defaultContact: Contact | null;
|
|
allContacts: Contact[];
|
|
};
|
|
|
|
constructor(companyData: Company, cwData?: typeof this.cw_Data) {
|
|
this.id = companyData.id;
|
|
this.name = companyData.name;
|
|
this.cw_Identifier = companyData.cw_Identifier;
|
|
this.cw_CompanyId = companyData.cw_CompanyId;
|
|
this.cw_Data = cwData;
|
|
}
|
|
|
|
/**
|
|
* Hydrate CW Data
|
|
*
|
|
* Fetches and populates the full ConnectWise company data
|
|
* (company, default contact, all contacts) if not already loaded.
|
|
*
|
|
* @returns {ThisType}
|
|
*/
|
|
public async hydrateCwData() {
|
|
if (this.cw_Data) return this;
|
|
|
|
const cwCompany = await fetchCwCompanyById(this.cw_CompanyId);
|
|
if (!cwCompany) return this;
|
|
|
|
const allContactsData = await connectWiseApi.get(
|
|
`${cwCompany._info.contacts_href}&pageSize=1000`,
|
|
);
|
|
|
|
// Derive default contact from allContacts instead of a separate CW call
|
|
const defaultContactId = cwCompany.defaultContact?.id;
|
|
const defaultContactData = defaultContactId
|
|
? ((allContactsData.data as any[]).find(
|
|
(c: any) => c.id === defaultContactId,
|
|
) ?? null)
|
|
: null;
|
|
|
|
this.cw_Data = {
|
|
company: cwCompany,
|
|
defaultContact: defaultContactData,
|
|
allContacts: allContactsData.data,
|
|
};
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Refresh Internal Company Data from ConnectWise
|
|
*
|
|
* This method fetches the latest company data from ConnectWise and updates
|
|
* the internal company information accordingly.
|
|
*
|
|
* @returns {ThisType} - Updated Controller
|
|
*/
|
|
public async refreshFromCW() {
|
|
const data = await updateCwInternalCompany(this.cw_CompanyId);
|
|
|
|
this.name = data?.name || this.name;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Fetch ConnectWise Company Data
|
|
*
|
|
* This method retrieves the latest company data directly from ConnectWise
|
|
* using the stored ConnectWise Company ID.
|
|
*
|
|
* @returns {Company}
|
|
*/
|
|
public async fetchCwData(): Promise<CWCompany | null> {
|
|
const data = await fetchCwCompanyById(this.cw_CompanyId);
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* Fetch Company Configurations
|
|
*
|
|
* This method retrieves the configurations associated with
|
|
* the company from ConnectWise.
|
|
*
|
|
* @returns {ProcessedConfiguration}
|
|
*/
|
|
public async fetchConfigurations() {
|
|
const data = await fetchCompanyConfigurations(this.cw_CompanyId);
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* Fetch Company Sites
|
|
*
|
|
* Retrieves all sites for this company from ConnectWise
|
|
* and returns them as serialized site objects.
|
|
*/
|
|
public async fetchSites() {
|
|
const sites = await fetchCompanySites(this.cw_CompanyId);
|
|
return sites.map(serializeCwSite);
|
|
}
|
|
|
|
/**
|
|
* Fetch Company Site by ID
|
|
*
|
|
* Retrieves a single site by its ConnectWise site ID
|
|
* and returns a serialized site object.
|
|
*
|
|
* @param cwSiteId - The ConnectWise site ID
|
|
*/
|
|
public async fetchSite(cwSiteId: number) {
|
|
const site = await fetchCompanySite(this.cw_CompanyId, cwSiteId);
|
|
return serializeCwSite(site);
|
|
}
|
|
|
|
public toJson(opts?: {
|
|
includeAddress: boolean;
|
|
includePrimaryContact: boolean;
|
|
includeAllContacts?: boolean;
|
|
}) {
|
|
return {
|
|
id: this.id,
|
|
name: this.name,
|
|
cw_Identifier: this.cw_Identifier,
|
|
cw_CompanyId: this.cw_CompanyId,
|
|
cw_Data: {
|
|
address: !opts?.includeAddress
|
|
? undefined
|
|
: {
|
|
line1: this.cw_Data?.company.addressLine1,
|
|
line2: this.cw_Data?.company.addressLine2 ?? null,
|
|
city: this.cw_Data?.company.city,
|
|
state: this.cw_Data?.company.state,
|
|
zip: this.cw_Data?.company.zip,
|
|
country: this.cw_Data?.company.country
|
|
? this.cw_Data.company.country.name
|
|
: "United States",
|
|
},
|
|
primaryContact: !opts?.includePrimaryContact
|
|
? undefined
|
|
: this.cw_Data?.defaultContact
|
|
? {
|
|
firstName: this.cw_Data.defaultContact.firstName,
|
|
lastName: this.cw_Data.defaultContact.lastName,
|
|
cwId: this.cw_Data.defaultContact.id,
|
|
inactive: this.cw_Data.defaultContact.inactiveFlag,
|
|
title: this.cw_Data.defaultContact.title,
|
|
phone: this.cw_Data.defaultContact.defaultPhoneNbr,
|
|
email: (() => {
|
|
if (!this.cw_Data?.defaultContact?.communicationItems)
|
|
return null;
|
|
return (
|
|
this.cw_Data.defaultContact.communicationItems.find(
|
|
(v) => v.type.name === "Email",
|
|
)?.value ?? null
|
|
);
|
|
})(),
|
|
}
|
|
: null,
|
|
allContacts: !opts?.includeAllContacts
|
|
? undefined
|
|
: this.cw_Data?.allContacts.map((contact) => ({
|
|
firstName: contact.firstName,
|
|
lastName: contact.lastName,
|
|
cwId: contact.id,
|
|
inactive: contact.inactiveFlag,
|
|
title: contact.title,
|
|
phone: contact.defaultPhoneNbr,
|
|
email: (() => {
|
|
if (!contact.communicationItems) return null;
|
|
return (
|
|
contact.communicationItems.find(
|
|
(v) => v.type.name === "Email",
|
|
)?.value ?? null
|
|
);
|
|
})(),
|
|
})),
|
|
},
|
|
};
|
|
}
|
|
}
|