From 24d0c066fd89448ca9763446febcd41d83358890 Mon Sep 17 00:00:00 2001 From: Jackson Roberts Date: Mon, 26 Jan 2026 18:14:28 -0600 Subject: [PATCH] Setup fetch and wip fetchall route for getting companies. --- src/api/companies/fetch.ts | 22 +++++++++++++ src/api/companies/fetchAll.ts | 31 ++++++++++++++++++ src/controllers/CompanyController.ts | 47 +++++++++++++++++++++++++++ src/managers/companies.ts | 20 ++++++++++++ src/modules/cw-utils/fetchCompany.ts | 19 +++++++++++ src/modules/cw-utils/updateCompany.ts | 24 ++++++++++++++ 6 files changed, 163 insertions(+) create mode 100644 src/api/companies/fetch.ts create mode 100644 src/api/companies/fetchAll.ts create mode 100644 src/controllers/CompanyController.ts create mode 100644 src/managers/companies.ts create mode 100644 src/modules/cw-utils/fetchCompany.ts create mode 100644 src/modules/cw-utils/updateCompany.ts diff --git a/src/api/companies/fetch.ts b/src/api/companies/fetch.ts new file mode 100644 index 0000000..d7345b3 --- /dev/null +++ b/src/api/companies/fetch.ts @@ -0,0 +1,22 @@ +import { Hono } from "hono/tiny"; +import { createRoute } from "../../modules/api-utils/createRoute"; +import { companies } from "../../managers/companies"; +import { apiResponse } from "../../modules/api-utils/apiResponse"; +import { ContentfulStatusCode } from "hono/utils/http-status"; +import { authMiddleware } from "../middleware/authorization"; + +/* /v1/company/[id] */ +export default createRoute( + "get", + ["/:identifier"], + async (c) => { + const company = await companies.fetch(c.req.param("identifier")); + + const response = apiResponse.successful( + "Company Fetched Successfully!", + company, + ); + return c.json(response, response.status as ContentfulStatusCode); + }, + authMiddleware({ permissions: ["company.fetch"] }), +); diff --git a/src/api/companies/fetchAll.ts b/src/api/companies/fetchAll.ts new file mode 100644 index 0000000..0eaa44b --- /dev/null +++ b/src/api/companies/fetchAll.ts @@ -0,0 +1,31 @@ +import { Hono } from "hono/tiny"; +import { createRoute } from "../../modules/api-utils/createRoute"; +import { companies } from "../../managers/companies"; +import { apiResponse } from "../../modules/api-utils/apiResponse"; +import { ContentfulStatusCode } from "hono/utils/http-status"; +import { authMiddleware } from "../middleware/authorization"; + +/* /v1/company/companies */ +export default createRoute( + "get", + ["/companies"], + async (c) => { + /** + * + * + * @TODO MAKE THIS WORK + * + * + * + */ + + const company = await companies.fetch(c.req.param("identifier")); + + const response = apiResponse.successful( + "Company Fetched Successfully!", + company, + ); + return c.json(response, response.status as ContentfulStatusCode); + }, + authMiddleware({ permissions: ["company.fetch"] }), +); diff --git a/src/controllers/CompanyController.ts b/src/controllers/CompanyController.ts new file mode 100644 index 0000000..a96e967 --- /dev/null +++ b/src/controllers/CompanyController.ts @@ -0,0 +1,47 @@ +import { Company } from "../../generated/prisma/client"; +import { updateCwInternalCompany } from "../modules/cw-utils/updateCompany"; + +/** + * 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; + + constructor(companyData: Company) { + this.id = companyData.id; + this.name = companyData.name; + this.cw_Identifier = companyData.cw_Identifier; + this.cw_CompanyId = companyData.cw_CompanyId; + } + + /** + * 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; + } + + public toJson() { + return { + id: this.id, + name: this.name, + cw_Identifier: this.cw_Identifier, + cw_CompanyId: this.cw_CompanyId, + }; + } +} diff --git a/src/managers/companies.ts b/src/managers/companies.ts new file mode 100644 index 0000000..434aae8 --- /dev/null +++ b/src/managers/companies.ts @@ -0,0 +1,20 @@ +import { prisma } from "../constants"; +import { CompanyController } from "../controllers/CompanyController"; + +export const companies = { + async fetch(identifier: string | number): Promise { + const search = await prisma.company.findFirst({ + where: { + OR: [ + { id: identifier as string }, + { cw_CompanyId: identifier as number }, + { cw_Identifier: identifier as string }, + ], + }, + }); + + if (!search) throw new Error("Unknown company."); + + return new CompanyController(search); + }, +}; diff --git a/src/modules/cw-utils/fetchCompany.ts b/src/modules/cw-utils/fetchCompany.ts new file mode 100644 index 0000000..b965c26 --- /dev/null +++ b/src/modules/cw-utils/fetchCompany.ts @@ -0,0 +1,19 @@ +import { connectWiseApi } from "../../constants"; +import { Company } from "../../types/ConnectWiseTypes"; + +export const fetchCwCompanyById = async ( + companyId: number, +): Promise => { + try { + const response = await connectWiseApi.get( + `/company/companies/${companyId}`, + ); + return response.data; + } catch (error) { + console.error( + `Error fetching company with ID ${companyId}:`, + (error as any).response?.data || error, + ); + return null; + } +}; diff --git a/src/modules/cw-utils/updateCompany.ts b/src/modules/cw-utils/updateCompany.ts new file mode 100644 index 0000000..17fd699 --- /dev/null +++ b/src/modules/cw-utils/updateCompany.ts @@ -0,0 +1,24 @@ +import { Company } from "../../../generated/prisma/client"; +import { prisma } from "../../constants"; +import { fetchCwCompanyById } from "./fetchCompany"; + +export const updateCwInternalCompany = async ( + companyId: number, +): Promise => { + const cwCompany = await fetchCwCompanyById(companyId); + if (!cwCompany) return null; + + const updatedCompany = await prisma.company.upsert({ + where: { cw_CompanyId: cwCompany.id }, + create: { + cw_CompanyId: cwCompany.id, + cw_Identifier: cwCompany.identifier, + name: cwCompany.name, + }, + update: { + name: cwCompany.name, + }, + }); + + return updatedCompany; +};