+8








6561b92f40
* Upgrade jsforce to 3.6.2
* Refactor connecting to Salesforce
* Revert yarn.lock changes
* Add `TASKER_ENABLE_CRM_EVENT_CREATION` to .env
* Add createCRMEvent scheduler
* Schedule CRM event creating in `EventManager`
* Add calendar event builder for CRM tasks
* Do not write to person record if fields don't exist
* Change type to expect string from tasker
* Create CRM event
* Create booking references
* Type fixes
* Migrate callback endpoint
* Add jsforce node dependency
* Migrate add endpoint
* Import
* Import package into crmService
* Use new package types
* Type fix
* Update vite config
* Push updated lockfile
* Attempt to bump platform/libraries to unlock jsforce
* Also update lockfile, naturally
* bump platform libraries
* feat: salesforce to tasker improvements (#18419)
* feat: salesforce to tasker
* refactor: event manager
* tests: add unit tests for create CRM Event
* Update vite.config
* Add jsforce to vite config
* Revert mint.json changes
* Default to not enabling
* Revert yarn.lock changes
* Remove `TASKER_ENABLE_CRM_EVENT_CREATION` variable
* Revert yarn.lock changes
* feat: Round Robin weights future members toggle (#17782)
Co-authored-by: Omar López <zomars@me.com>
* detailed customer card (#18511)
Co-authored-by: Omar López <zomars@me.com>
* chore: app router - all sub-pages in `/apps` (#16976)
* chore: apps/[slug] remove pages router
* remove apps/[slug] pages from /future
* chore: apps/installed remove pages router
* chore: apps/installation remove pages router
* remove Head element
* fix metadata
* fix test
* fix another test
* chore: apps/categories remove pages router
* revert unneeded changes
* update middleware
* Remove <Head>
* remove unused import and code
* remove unused import and code again
* fix
* fix category page
* add split icon
* add /routing paths to middleware matcher
* wip
* remove HeadSeo from App.tsx
* clean up head-seo test
* add generateAppMetadata
* use generateAppMetadata in apps/[slug] page
* delete file
* remove log
* fix
* fix
* fix apps/installed pages
* fix cateogires pages
* fix
* fix imports
* wip
* fix
* fix
* fix metadata
* fix
* redirect /apps/routing-forms to /routing
* replace all usages of /apps/routing-forms to /routing
* better naming
* /routing -> /routing/forms
* fix
* fix
* fix
* fix
* remove backPath as it is irrelevant when withoutMain is true
* fix type checks
* fix type check in apps/[slug]
* refactors
* fix
* fix test
* fix
* fix
* fix
* Replace multiple leading slashes with a single slash
* migrate routing-forms too
* add re routing
* fix
* add redirection
---------
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
* chore: app router 404 page (#18597)
* wip
* wip
* fix not found page
* render middleware for /settings pages
* fix
* remove global-error page
* add metadata to not-found page
* make not-found page static
* remove 404
* adding not-found to middleware is not necessary
* add every routes to config.matcher
* fix test
* fix style
* use i18n string
* fix tests
* fix
* fix
* revert unneeded changes
* fix
* fix
* fix
* fix style
* fix
* remove 404
* remove log
* fix
* fix
* fix
* fix
* better naming
* parallel testing
---------
Co-authored-by: Benny Joo <sldisek783@gmail.com>
* feat: render custom error page for unexpected sever error + remove` pages/_error` (#18606)
* remove page/_error
* refactor app/error
* fix: app/not-found cannot be a static page (#18610)
* Async False (#18611)
* chore: redirect to /500 if pathname does not exist + better error handling (#18615)
* fix lint error
* fix booking page and better error handling
* chore: gracefully handle 404s from pages router's dynamic pages + tests (#18618)
* restore pages/_error
* set custom header in pages/_error
* handle it in middleware
* add test
* remove logs
* better test description
* chore: try using custom 404 in pages/_error (#18622)
* fix: parsing teamId (#18623)
* chore: restore error pages for pages router (#18625)
* disable emails to all guests (#18628)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
* revert: "feat: bulk shorten links with dub.links.createMany (#18539)" (#18587)
This reverts commit 4902c6a0f8.
Co-authored-by: Alex van Andel <me@alexvanandel.com>
* chore: release v4.8.18
* fix: disable sending sms when email is present (#18632)
* fix: disable sending sms when email is present
* fix: update test
* fix: main lint errors (#18634)
* fix: error-page.tsx related lint errors
* fix: lint no continue-on-error
* Adding more lint fixes
* Bring back annotate code linting results
* Bring back linting continue-on-error
* Slimline lint
* feat: do not show automation webhooks in webhook list (#18607)
* fix: make ESLint work and fix lint errors that were undetected before (#18639)
* fix eslint config
* fix
* add it to dev dep
* fix
* sync eslint version
* force ts-node to compile our ESLint plugin's TS files into CommonJS (which ESLint requires)
* fix some lint errors
* fix lint errors
* remove duplicate classname
* make @typescript-eslint/ban-types a warn for packages/trpc files
* fix lint errors in trpc
* fix lint errors in trpc - 2
* fix
* fix
* fix lint warnings
* chore: clean up config.matcher in middleware (#18638)
Co-authored-by: Alex van Andel <me@alexvanandel.com>
* Allow lint to error but continue (unblock pipeline)
* fix: potential fix for flaky layout shift (#18651)
* potential fix: layout shift
* fix lint error
* feat: update translations via @replexica (#18598)
* chore: sync with main
* feat: update translations via @replexica
---------
Co-authored-by: Replexica <support@replexica.com>
* Update yarn.lock
* nit: let tasker handle payload stringification
---------
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: Morgan Vernay <morgan@cal.com>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Nizzy <140507264+nizzyabi@users.noreply.github.com>
Co-authored-by: Benny Joo <sldisek783@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: GitHub Actions <github-actions@github.com>
Co-authored-by: Kartik Saini <41051387+kart1ka@users.noreply.github.com>
Co-authored-by: Calcom Bot <109866826+calcom-bot@users.noreply.github.com>
Co-authored-by: Replexica <support@replexica.com>
145 lines
4.2 KiB
TypeScript
145 lines
4.2 KiB
TypeScript
import type { Prisma } from "@prisma/client";
|
|
|
|
import { eventTypeAppCardZod } from "@calcom/app-store/eventTypeAppCardZod";
|
|
import logger from "@calcom/lib/logger";
|
|
import prisma from "@calcom/prisma";
|
|
import { BookingStatus } from "@calcom/prisma/enums";
|
|
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
|
|
|
import buildCalendarEvent from "./lib/buildCalendarEvent";
|
|
import { createCRMEventSchema } from "./schema";
|
|
|
|
const log = logger.getSubLogger({ prefix: [`[[tasker] createCRMEvent`] });
|
|
|
|
export async function createCRMEvent(payload: string): Promise<void> {
|
|
try {
|
|
const parsedPayload = createCRMEventSchema.safeParse(JSON.parse(payload));
|
|
|
|
if (!parsedPayload.success) {
|
|
throw new Error(`malformed payload in createCRMEvent: ${parsedPayload.error}`);
|
|
}
|
|
const { bookingUid } = parsedPayload.data;
|
|
|
|
const booking = await prisma.booking.findUnique({
|
|
where: {
|
|
uid: bookingUid,
|
|
status: BookingStatus.ACCEPTED,
|
|
},
|
|
include: {
|
|
user: {
|
|
select: {
|
|
name: true,
|
|
email: true,
|
|
locale: true,
|
|
username: true,
|
|
timeZone: true,
|
|
},
|
|
},
|
|
eventType: {
|
|
select: {
|
|
metadata: true,
|
|
},
|
|
},
|
|
references: {
|
|
select: {
|
|
type: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!booking) {
|
|
throw new Error(`booking not found for uid: ${bookingUid}`);
|
|
}
|
|
|
|
if (!booking.user) {
|
|
throw new Error(`user not found for uid: ${bookingUid}`);
|
|
}
|
|
|
|
const eventTypeMetadata = EventTypeMetaDataSchema.safeParse(booking.eventType?.metadata);
|
|
|
|
if (!eventTypeMetadata.success) {
|
|
throw new Error(`malformed event type metadata: ${eventTypeMetadata.error}`);
|
|
}
|
|
|
|
const eventTypeAppMetadata = eventTypeMetadata.data?.apps;
|
|
|
|
if (!eventTypeAppMetadata) {
|
|
throw new Error(`event type app metadata not found for booking ${bookingUid}`);
|
|
}
|
|
|
|
const calendarEvent = await buildCalendarEvent(bookingUid);
|
|
|
|
const bookingReferencesToCreate: Prisma.BookingReferenceUncheckedCreateInput[] = [];
|
|
|
|
// Find enabled CRM apps for the event type
|
|
for (const appSlug of Object.keys(eventTypeAppMetadata)) {
|
|
try {
|
|
const appData = eventTypeAppMetadata[appSlug as keyof typeof eventTypeAppMetadata];
|
|
const appParse = eventTypeAppCardZod.safeParse(appData);
|
|
|
|
if (!appParse.success) {
|
|
log.error(`Error parsing event type app data for bookingUid ${bookingUid}`, appParse?.error);
|
|
continue;
|
|
}
|
|
|
|
const app = appParse.data;
|
|
|
|
if (
|
|
!app.appCategories ||
|
|
!app.appCategories.some((category: string) => category === "crm") ||
|
|
!app.enabled ||
|
|
!app.credentialId
|
|
)
|
|
continue;
|
|
|
|
const crmCredential = await prisma.credential.findUnique({
|
|
where: {
|
|
id: app.credentialId,
|
|
},
|
|
include: {
|
|
user: {
|
|
select: {
|
|
email: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!crmCredential) {
|
|
throw new Error(`Credential not found for credentialId: ${app.credentialId}`);
|
|
}
|
|
|
|
const CrmManager = (await import("@calcom/core/crmManager/crmManager")).default;
|
|
|
|
const crm = new CrmManager(crmCredential, app);
|
|
|
|
const results = await crm.createEvent(calendarEvent).catch((error) => {
|
|
log.error(`Error creating crm event for credentialId ${app.credentialId}`, error);
|
|
});
|
|
|
|
if (results) {
|
|
bookingReferencesToCreate.push({
|
|
type: crmCredential.type,
|
|
uid: results.id,
|
|
meetingId: results.id,
|
|
credentialId: crmCredential.id,
|
|
bookingId: booking.id,
|
|
});
|
|
}
|
|
} catch (error) {
|
|
log.error(`Error processing CRM app ${appSlug} for booking ${bookingUid}:`, error);
|
|
// Continue with next app even if one fails
|
|
continue;
|
|
}
|
|
}
|
|
|
|
await prisma.bookingReference.createMany({
|
|
data: bookingReferencesToCreate,
|
|
});
|
|
} catch (error) {
|
|
log.error(`Error in createCRMEvent for payload: ${payload}:`, error);
|
|
throw error;
|
|
}
|
|
}
|