|
45185
|
1622
|
16
|
2026-05-14T14:24:05.350072+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768645350_m2.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.2962101,"top":1.0,"width":0.03856383,"height":-0.019952059},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.33477393,"top":1.0,"width":0.122340426,"height":-0.019952059},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.5731383,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.5884308,"top":1.0,"width":0.076130316,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.66456115,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.67586434,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.6871675,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.7150931,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.72639626,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.73769945,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"6","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","depth":4,"bounds":{"left":0.39261967,"top":0.14844373,"width":0.31615692,"height":0.8515563},"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
60362959092589173
|
-2691170164485591123
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45184
|
1621
|
28
|
2026-05-14T14:24:05.366794+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768645366_m1.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.054166667,"top":0.027777778,"width":0.08055556,"height":0.035555556},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.13472222,"top":0.027777778,"width":0.25555557,"height":0.035555556},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.6326389,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.6645833,"top":0.027777778,"width":0.15902779,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.82361114,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.8472222,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.87083334,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.9291667,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9527778,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9763889,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"bounds":{"left":0.78055555,"top":0.2777778,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.80138886,"top":0.2777778,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.8215278,"top":0.27555555,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.8368056,"top":0.27555555,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false}]...
|
-8990710920805402580
|
-2691170164485591123
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45183
|
1621
|
27
|
2026-05-14T14:23:54.902821+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768634902_m1.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.054166667,"top":0.027777778,"width":0.08055556,"height":0.035555556},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.13472222,"top":0.027777778,"width":0.25555557,"height":0.035555556},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.6326389,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.6645833,"top":0.027777778,"width":0.15902779,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.82361114,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.8472222,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.87083334,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.9291667,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9527778,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9763889,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"bounds":{"left":0.78055555,"top":0.2777778,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.80138886,"top":0.2777778,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.8215278,"top":0.27555555,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.8368056,"top":0.27555555,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.85486114,"top":0.31,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.87291664,"top":0.31,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.9138889,"top":0.31,"width":0.059027776,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"bounds":{"left":0.8645833,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.8854167,"top":0.34444445,"width":0.015277778,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.9048611,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"4","depth":4,"bounds":{"left":0.92569447,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.9458333,"top":0.3422222,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.9611111,"top":0.3422222,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","depth":4,"on_screen":true,"value":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.025,"top":0.06666667,"width":0.050694443,"height":0.034444444},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
3382584868951134281
|
6551498163460912845
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
45181
|
NULL
|
NULL
|
NULL
|
|
45182
|
1622
|
15
|
2026-05-14T14:23:54.568655+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768634568_m2.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.2962101,"top":1.0,"width":0.03856383,"height":-0.019952059},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.33477393,"top":1.0,"width":0.122340426,"height":-0.019952059},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.5731383,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.5884308,"top":1.0,"width":0.076130316,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.66456115,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.67586434,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.6871675,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.7150931,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.72639626,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.73769945,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"6","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","depth":4,"bounds":{"left":0.39195478,"top":0.3735036,"width":0.31615692,"height":0.62649643},"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"}]...
|
5722231885167079023
|
-2691170301924544595
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3...
|
45180
|
NULL
|
NULL
|
NULL
|
|
45181
|
1621
|
26
|
2026-05-14T14:23:52.276580+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768632276_m1.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:23:52* :QProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php:=custom.log€ ConnectionStateTraUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php© CrmHelperReposito© FilterJoinedParticip• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpWriteCrmTrait.php X© ActivityPlaybookTrait.phpT OpportunitySyncab© CrmHelperRepository.php© AccountController.phpT IntegrationAppTrait.php.env.staging.envv HubspotDetachActivityObject.phpC RematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.php© Client.php18D AccountSyncStrate› DJ ActionsD ContactSyncStrate!› O DTO› O Fields› D JournalMetadata© HubspotPaginationService.phptrait WriteCrmTrait* @throws HubspotException* @throws BadRequest*/1 usageHandleHubspotRateLimit.php19525354A8 ж6^v OpportunitySyncSti55private function buildConferencePayload(Activity Sactivity): Activity> [ Concerns56© HubspotLastMor57$decorator = $this->getDecorateActivity();© HubspotLastMor58© HubspotLastMor59© HubspotLastMor60© HubspotLastMor61© HubspotSingleS:62© HubspotSyncStr63$engagement= ['active' => true,'ownerId' = $this->profile->getCrmProviderId®,'timestamp' => $decorator->formatStartTime(Sactivity),'type' => 'MEETING',© HubspotWebhoc64]:v D Pagination65© HubspotPaginati66© PaginationConfig67if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType))) {Sengagement['activityType'] = $activity->getActivityType()->getName();© PaginationState.68> D ProspectSearchStra69› [ Redis70v D ServiceTraits71€ OpportunitySync72$metadata = ['meetingOutcome' => $decorator->convertMeetingOutcome(Sactivity),'internalMeetingNotes' => $decorator-›generateDescription($activity),© SyncCrmEntities73+ SyncFieldsTrait./74T WriteCrmTrait.pl75// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a ‹232D Utils76if (! $activity->hasCrmProviderId)) {D Webhook77if (Sactivity->hasActualStartTime() && $activity->hasActualEndTime)) {D— 211212-213214215216217218219-220221222223224225=226227-228229230231— 233 v234@ RatchSvneCnllertn78Smetadatal 'startTime'l = Sdecorator->formatStartTime(Sactivitv):Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial,1 on u.id= sa.:1..n<->1: on t.L_id = 1052 andIMaccounts wheiactivities67:13UTF-8Co 4 spaces...
|
NULL
|
2572463782370577634
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:23:52* :QProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php:=custom.log€ ConnectionStateTraUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php© CrmHelperReposito© FilterJoinedParticip• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpWriteCrmTrait.php X© ActivityPlaybookTrait.phpT OpportunitySyncab© CrmHelperRepository.php© AccountController.phpT IntegrationAppTrait.php.env.staging.envv HubspotDetachActivityObject.phpC RematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.php© Client.php18D AccountSyncStrate› DJ ActionsD ContactSyncStrate!› O DTO› O Fields› D JournalMetadata© HubspotPaginationService.phptrait WriteCrmTrait* @throws HubspotException* @throws BadRequest*/1 usageHandleHubspotRateLimit.php19525354A8 ж6^v OpportunitySyncSti55private function buildConferencePayload(Activity Sactivity): Activity> [ Concerns56© HubspotLastMor57$decorator = $this->getDecorateActivity();© HubspotLastMor58© HubspotLastMor59© HubspotLastMor60© HubspotLastMor61© HubspotSingleS:62© HubspotSyncStr63$engagement= ['active' => true,'ownerId' = $this->profile->getCrmProviderId®,'timestamp' => $decorator->formatStartTime(Sactivity),'type' => 'MEETING',© HubspotWebhoc64]:v D Pagination65© HubspotPaginati66© PaginationConfig67if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType))) {Sengagement['activityType'] = $activity->getActivityType()->getName();© PaginationState.68> D ProspectSearchStra69› [ Redis70v D ServiceTraits71€ OpportunitySync72$metadata = ['meetingOutcome' => $decorator->convertMeetingOutcome(Sactivity),'internalMeetingNotes' => $decorator-›generateDescription($activity),© SyncCrmEntities73+ SyncFieldsTrait./74T WriteCrmTrait.pl75// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a ‹232D Utils76if (! $activity->hasCrmProviderId)) {D Webhook77if (Sactivity->hasActualStartTime() && $activity->hasActualEndTime)) {D— 211212-213214215216217218219-220221222223224225=226227-228229230231— 233 v234@ RatchSvneCnllertn78Smetadatal 'startTime'l = Sdecorator->formatStartTime(Sactivitv):Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial,1 on u.id= sa.:1..n<->1: on t.L_id = 1052 andIMaccounts wheiactivities67:13UTF-8Co 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45180
|
1622
|
14
|
2026-05-14T14:23:50.173150+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768630173_m2.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.2962101,"top":1.0,"width":0.03856383,"height":-0.019952059},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.33477393,"top":1.0,"width":0.122340426,"height":-0.019952059},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.5731383,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.5884308,"top":1.0,"width":0.076130316,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.66456115,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.67586434,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.6871675,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.7150931,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button"}]...
|
-5784594327568142026
|
-7196678489907033719
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Jiminny... ~ActivityFilesLater@ jiminny-x-integrati• plattorm-inner-teamE Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity lab# engineering# general#jiminny-bgac nlattorm-nckets# product launches# random# releases# sofia-officed sunport# thank-yous# the people of iimi... Direct messages• 8la 62% Galya Dimitrovavasil VasilevM Stefka StovanovaSg: Todor StamatovMario GeorgievNiudlay lanay. James Graham "* Stoyan Tanevo Stelivan Georgiev( Petko Kashinski*. Lukas Kovali...::: AnnsToastS lira Gloud6d Huddle with Aneliva Angelova* Aneliya Angelova &• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някъде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpotl Optimise CRM rematct(7 OpenRosdy for OA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira* SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle (LIVE 4:06 PMAneliva Angelova is here toolAneliva Angelova 4:44 PN11512582Lukas Kovalik M 5.16 PNcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-vne' annlication/ison'--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIr7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIđ 0Pmv Q SearchDate ModifiedYesterdav at 13.34Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:32Yesterday at 13:31Yesterdav at 13:30Yesterday at 13:30Yesterday at 13.29Yesterdav at 13:28resterday at 15.21Yesterdav at 13:27Yesterday at 13:26Yesterday at 13:26Yesterday at 13:23Yesterdav at 13:25Yesterday at 13.24Yesterdav at 13:23Yesterday at 13:22Testerady dl ls.2.Yesterday at 13:21Voctordau at 12:20lYesterday at 13.19Yesterdav at 13:19Yesterdav at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.16Yecterdav at 12:15Yesterdav at 13:15Yesterday at 13-14Yesterdav at 13:14Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:12Yesterday at 13.11Yesterdav at 13:10Yesterday at 13:10Yesterday at 13:09Yoctorday at 12:09Yesterdav at 13:08Yesterday at 13.0Yecterdav at 12:07Yesterday at 13:06Yesterdav at 13:0529 K:MPEG-4 movie6 KB12 KBMDEG-A movieMPEG-4 movieMPEG-4 movie7 KBI8 KB37 KB10 K:MPEG-4 movie7 KBMDEG-A movie8 KEMPEG-4 movie8 KBI72 KB14 KB13 KEMPEG-4 movieMPEG-4 movie9 KBMDECA mavie18 KB12 KB|MPEG-4 movie10 KRI16 KB6 KBMPEG-1 movidMPEG-4 movie6KEMPEG-4 movie12 KBMPEG-4 movie23 KB8 K:MPEG-4 movie6 KB6 KB11 KBMDSG.A movicMPEG-4 movie11 KE20 KBMPEG-4 movieMPEG-4 movie34 KB10 K:MPEG-4 movie7 Kp5 KB11 KBMDSG.A movidMPEG-4 movie26KPMDEG-A movie111 KB MPEG-4 movie102 KB88 KB59 KB98 KB97 KBMPEG-4 movieMDEC.A moviaMPEG-4 movieRAKRMDEG-A movie44 KB93 KBMPEG-4 movie78 K:MPEG-A movie50 KBMPEG-4 movie58 KB27 KB7 KPMPEG-4 movieMDEG.A movio12 KB32 KBMPEG-4 movie17 Kг19 KBMDEC A movid32 KB10K8MPEG-4 movieAl Notes: OffLeave• • CFavourites• jiminny• Recents* ApplicationsiCloud• iCloud Drive992 Svnc tolde0 DXP4800PLUS-B5F49 Networl• CRMI• Orange• Red|• Yellow• Green• Purple•) All lags..IhlDownloadsNameLoom.pkgAlfred copv.alfredoreterences=KeychronAssist-1.0.2 (1).dmeKeychronAssist-1.0.2.dmgmazanoke-images-yWJo.zioPhotos-3-001.zip• Transcript.pd→mage U.loge1 Orioninstaller.dma_image.jpg- image (2).1pc• ПO-22221726037035-004-001_ORGES.pdf%D0%9F%D0%9E-22221726037035-004-001 archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterencesСE 060209С О000000026571172 CWICT 0Р70501260015900 ndt= 27022026_0000000026574472_ SWIFT_ [IBAN].pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001reportxmmi=pdt.odiB pdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfP Kdf-a,k Ffmiv Tree.sebitwarden export 20251031122528.isonlKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst aid_notes_complete.docxrenortl2).esviconfig.vmlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.isonnokc.901a6502.6667.A62h-062 ccu•AlfredwPmazanoko.imnaoc.YWIfана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик iро• Dhotac 2.001Q SearchKind00,4 MD55.9 MBinstdlle..dckageAlfred...ferences10,1 MB10,1 MBIL MBDisk ImageDisk ImageLiP archive6.6 MBZIp archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDE Document140 KbZIP archive148 KВ148 KB122 KBZIP archivelZIP archiveXML document111 KBAlfred...ferences94 KBDDE Documont92 KBPDr DocumentK:PDF Document91 KB91 KBXML document30 KBn0kpDDE Nocumont28 KBPDF Document28 KRPDE Document28 KB27 KBDocument14 KB11 KB6 KB6KBJSONINCV NacumontZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBVAMI dosumon1 KB029 buteccSV Documenthttlicence183 bytesZero butesJSONAlfrod foronso!Zero bytesFolde1.9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9,62 GB availabld• Inu 14 Mау 1/•23.44Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 ,Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3712 Goh 2006 9t 11:5 A1Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nau 2025 4+ 17:506 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0419 Mar 2026 at 11:55|10 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:362616 Oct 2025 aт 16:0122 Aar 2026 at 12:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45179
|
1621
|
25
|
2026-05-14T14:23:50.137655+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768630137_m1.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:23:50* :QProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php:=custom.log€ ConnectionStateTraUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php© CrmHelperReposito© FilterJoinedParticip• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpWriteCrmTrait.php X© ActivityPlaybookTrait.phpT OpportunitySyncab© CrmHelperRepository.php© AccountController.phpT IntegrationAppTrait.php.env.staging.envv HubspotDetachActivityObject.phpC RematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.php© Client.php18D AccountSyncStrate> DJ ActionsD ContactSyncStrate!› O DTO› O Fields› D JournalMetadata© HubspotPaginationService.phptrait WriteCrmTrait* @throws HubspotException* @throws BadRequest*/1 usageHandleHubspotRateLimit.php19525354A8 ж6^v OpportunitySyncSti55private function buildConferencePayload(Activity Sactivity): Activity> [ Concerns56© HubspotLastMor57$decorator = $this->getDecorateActivity();© HubspotLastMor58© HubspotLastMor59© HubspotLastMor60© HubspotLastMor61© HubspotSingleS:62© HubspotSyncStr63$engagement = l'active' => true,'ownerId' = $this->profile->getCrmProviderId®,'timestamp' => $decorator->formatStartTime(Sactivity),'type' => 'MEETING',© HubspotWebhoc64]:v D Pagination65© HubspotPaginati66© PaginationConfig67if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType))) {$engagement['activityType'] = $activity->getActivityType()->getNameO:© PaginationState.68> D ProspectSearchStra69› [ Redis70v D ServiceTraits71€ OpportunitySync72$metadata = ['meetingOutcome' => $decorator->convertMeetingOutcome(Sactivity),'internalMeetingNotes' => $decorator-›generateDescription($activity),© SyncCrmEntities73+ SyncFieldsTrait./74T WriteCrmTrait.pl75// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a ‹232D Utils76if (! $activity->hasCrmProviderId)) {D Webhook77if (Sactivity->hasActualStartTime() && $activity->hasActualEndTime)) {D— 211212- =226227- 228229230231- 233 v234@ RatchSvneCnllertn78Smetadatal 'startTime'l = Sdecorator->formatStartTime(Sactivitv):Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial,1 on u.id= sa.:1..n<->1: on t.L_id = 1052 andIMaccounts wheiactivities66:60UTF-8Co 4 spaces...
|
NULL
|
-6670788643496401873
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:23:50* :QProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php:=custom.log€ ConnectionStateTraUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php© CrmHelperReposito© FilterJoinedParticip• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpWriteCrmTrait.php X© ActivityPlaybookTrait.phpT OpportunitySyncab© CrmHelperRepository.php© AccountController.phpT IntegrationAppTrait.php.env.staging.envv HubspotDetachActivityObject.phpC RematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.php© Client.php18D AccountSyncStrate> DJ ActionsD ContactSyncStrate!› O DTO› O Fields› D JournalMetadata© HubspotPaginationService.phptrait WriteCrmTrait* @throws HubspotException* @throws BadRequest*/1 usageHandleHubspotRateLimit.php19525354A8 ж6^v OpportunitySyncSti55private function buildConferencePayload(Activity Sactivity): Activity> [ Concerns56© HubspotLastMor57$decorator = $this->getDecorateActivity();© HubspotLastMor58© HubspotLastMor59© HubspotLastMor60© HubspotLastMor61© HubspotSingleS:62© HubspotSyncStr63$engagement = l'active' => true,'ownerId' = $this->profile->getCrmProviderId®,'timestamp' => $decorator->formatStartTime(Sactivity),'type' => 'MEETING',© HubspotWebhoc64]:v D Pagination65© HubspotPaginati66© PaginationConfig67if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType))) {$engagement['activityType'] = $activity->getActivityType()->getNameO:© PaginationState.68> D ProspectSearchStra69› [ Redis70v D ServiceTraits71€ OpportunitySync72$metadata = ['meetingOutcome' => $decorator->convertMeetingOutcome(Sactivity),'internalMeetingNotes' => $decorator-›generateDescription($activity),© SyncCrmEntities73+ SyncFieldsTrait./74T WriteCrmTrait.pl75// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a ‹232D Utils76if (! $activity->hasCrmProviderId)) {D Webhook77if (Sactivity->hasActualStartTime() && $activity->hasActualEndTime)) {D— 211212- =226227- 228229230231- 233 v234@ RatchSvneCnllertn78Smetadatal 'startTime'l = Sdecorator->formatStartTime(Sactivitv):Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial,1 on u.id= sa.:1..n<->1: on t.L_id = 1052 andIMaccounts wheiactivities66:60UTF-8Co 4 spaces...
|
45178
|
NULL
|
NULL
|
NULL
|
|
45178
|
1621
|
24
|
2026-05-14T14:23:42.176417+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768622176_m1.jpg...
|
PhpStorm
|
faVsco.js – CrmHelperRepository.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelplhl•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestv100% (C478• Thu 14 May 17:23:41QProject v© ReportController.php© AutomatedReportGenerated.php:18TrackAutomatedReportGeneratedEvent.phpPlaybackController.php• CrmObjectsO DecorateActivity> D Dummyv D Helpers.T ActivityPlaybookTra© Arraylterator.php+ ConnectionState Tra© CrmHelperReposito© FilterJoinedParticipT OpportunitySyncab1314v D HubspotD AccountSyncStrate15› D Actions16D ContactSyncStrate!17> ODTO18› OJ Fields19› 0 Journal27Metadata28v OpportunitySyncSti> O Concerns35© HubspotLastMor© HubspotLastMor3637© HubspotLastMor© HubspotLastMor3839© HubspotLastMor© HubspotSingleS:40© HubspotSyncStr4142© HubspotWebhocv D Pagination43© HubspotPaginati49© PaginationConfig50© PaginationState.> O ProspectSearchStra• Redisv O ServiceTraits(. OnnortunitvSvnrUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.php© ActivityPlaybookTrait.php© CrmHelperRepository.php xAccountController.phpT IntegrationAppTrait.php.env.staging= .env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.phpHandleHubspotRateLimit.phpUSe/***/* A collection of DB-related internal functionalities or all CRMs.class CrmHelperRepositorypublic function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory{...}1 usagepublic function getActivityFieldValueByName(Field $activityField, string $categoryName): ?FieldValue{…}1 usagepublic function existsActivityFieldValueByName(Field $activityField, string $categoryName): boolreturn $activityField->values()->where( column: 'Label', $categohyName)->exists();public function hasFeature(Activity $activity, FeatureEnum $featureName): boolf...}Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)=custom.log=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]D V234Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !M crm_layout_eilIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial.1 on u.id= sa.:1..n<->1: on t.Lid = 1052 andIMaccounts wheiactivities39:37UTF-8W Windsurf TeamsCo 4 spaces...
|
NULL
|
2342549807754423779
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelplhl•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestv100% (C478• Thu 14 May 17:23:41QProject v© ReportController.php© AutomatedReportGenerated.php:18TrackAutomatedReportGeneratedEvent.phpPlaybackController.php• CrmObjectsO DecorateActivity> D Dummyv D Helpers.T ActivityPlaybookTra© Arraylterator.php+ ConnectionState Tra© CrmHelperReposito© FilterJoinedParticipT OpportunitySyncab1314v D HubspotD AccountSyncStrate15› D Actions16D ContactSyncStrate!17> ODTO18› OJ Fields19› 0 Journal27Metadata28v OpportunitySyncSti> O Concerns35© HubspotLastMor© HubspotLastMor3637© HubspotLastMor© HubspotLastMor3839© HubspotLastMor© HubspotSingleS:40© HubspotSyncStr4142© HubspotWebhocv D Pagination43© HubspotPaginati49© PaginationConfig50© PaginationState.> O ProspectSearchStra• Redisv O ServiceTraits(. OnnortunitvSvnrUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.php© ActivityPlaybookTrait.php© CrmHelperRepository.php xAccountController.phpT IntegrationAppTrait.php.env.staging= .env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.phpHandleHubspotRateLimit.phpUSe/***/* A collection of DB-related internal functionalities or all CRMs.class CrmHelperRepositorypublic function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory{...}1 usagepublic function getActivityFieldValueByName(Field $activityField, string $categoryName): ?FieldValue{…}1 usagepublic function existsActivityFieldValueByName(Field $activityField, string $categoryName): boolreturn $activityField->values()->where( column: 'Label', $categohyName)->exists();public function hasFeature(Activity $activity, FeatureEnum $featureName): boolf...}Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)=custom.log=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]D V234Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !M crm_layout_eilIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial.1 on u.id= sa.:1..n<->1: on t.Lid = 1052 andIMaccounts wheiactivities39:37UTF-8W Windsurf TeamsCo 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45177
|
1622
|
13
|
2026-05-14T14:23:39.593444+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768619593_m2.jpg...
|
PhpStorm
|
faVsco.js – CrmHelperRepository.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterdav at 13.33Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:31Yesterday at 13:30Yesterdav at 13:30Yesterday at 13:29Yesterday at 13.28Yesterday at 13:28resterday at 15.21Yesterdav at 13:26Yesterday at 13:26Yesterday at 13:25Yesterday at 13:23Yesterday at 13:24resterday at 13-43Yesterdav at 13:22Yesterday at 13:20Yesterday at 13:20Yesterday at 13.19Yesterdav at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.15Yecterdav at 12:15Yesterday at 13:14Yesterday at 13-14Yesterdav at 13:13Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:11Yesterday at 13:10Yesterdav at 13:10Yesterday at 13:09Yesterday at 13:08Yoctorday at 12:09Yesterday at 13.0/Yocterdav at 13:06Yesterday at 13:06Yesterdav at 13:05MPEG-4 movie12 KBMPEG-4 movie9 KBMPEG-4 movieMPEG-4 movie8 KE37 KB10 KBMPEG-4 movie7 K:8 KBMPEG-4 movie9 KBMPEG-4 movie72 KBMPEG-4 movie14 KB15 KbMPEG-4 movie9 K:18 KBMPEG-4 movie12 KB10 K:16 KRIMPEG-4 movieMPEG-4 movie6 KBMPEG-4 movie12 KE23 KBMPEG-4 movie8 KB6 KB1MPEG-4 movie6 KBMPEG-4 movie11 KB11 KBMPEG-4 movie20 KEMPEG-4 movie34 KBMPEG-4 movie10 KB7K:MPEG-4 movie5 KBMPEG-4 movie11 KB26 KBMPEG-4 movie111 KPMPEG-4 movie102 KBMPEG-4 movie88 KB59 K:MPEG-4 movie98 KBMPEG-4 movie97 KB66 KBЛAKEMPEG-4 movieMDEG-A movie93 KB78 KBMPEG-4 movie50 K:MPEG-A movid58 KB MPEG-4 movie27 KB7 KB112 KрMPEG-4 movieMPEG-4 movie32 KB17 KBMPEG-4 movie19 Kг32 KBMPEG-4 movie10 KB24 K8MPEG-4 movieFavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-ywJo.ziPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dma- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.63 GB availabld• Inu 14 Mау 1/•23.34Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
-5006563693464471080
|
NULL
|
click
|
ocr
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterdav at 13.33Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:31Yesterday at 13:30Yesterdav at 13:30Yesterday at 13:29Yesterday at 13.28Yesterday at 13:28resterday at 15.21Yesterdav at 13:26Yesterday at 13:26Yesterday at 13:25Yesterday at 13:23Yesterday at 13:24resterday at 13-43Yesterdav at 13:22Yesterday at 13:20Yesterday at 13:20Yesterday at 13.19Yesterdav at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.15Yecterdav at 12:15Yesterday at 13:14Yesterday at 13-14Yesterdav at 13:13Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:11Yesterday at 13:10Yesterdav at 13:10Yesterday at 13:09Yesterday at 13:08Yoctorday at 12:09Yesterday at 13.0/Yocterdav at 13:06Yesterday at 13:06Yesterdav at 13:05MPEG-4 movie12 KBMPEG-4 movie9 KBMPEG-4 movieMPEG-4 movie8 KE37 KB10 KBMPEG-4 movie7 K:8 KBMPEG-4 movie9 KBMPEG-4 movie72 KBMPEG-4 movie14 KB15 KbMPEG-4 movie9 K:18 KBMPEG-4 movie12 KB10 K:16 KRIMPEG-4 movieMPEG-4 movie6 KBMPEG-4 movie12 KE23 KBMPEG-4 movie8 KB6 KB1MPEG-4 movie6 KBMPEG-4 movie11 KB11 KBMPEG-4 movie20 KEMPEG-4 movie34 KBMPEG-4 movie10 KB7K:MPEG-4 movie5 KBMPEG-4 movie11 KB26 KBMPEG-4 movie111 KPMPEG-4 movie102 KBMPEG-4 movie88 KB59 K:MPEG-4 movie98 KBMPEG-4 movie97 KB66 KBЛAKEMPEG-4 movieMDEG-A movie93 KB78 KBMPEG-4 movie50 K:MPEG-A movid58 KB MPEG-4 movie27 KB7 KB112 KрMPEG-4 movieMPEG-4 movie32 KB17 KBMPEG-4 movie19 Kг32 KBMPEG-4 movie10 KB24 K8MPEG-4 movieFavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-ywJo.ziPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dma- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.63 GB availabld• Inu 14 Mау 1/•23.34Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
45174
|
NULL
|
NULL
|
NULL
|
|
45176
|
1621
|
23
|
2026-05-14T14:23:39.593326+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768619593_m1.jpg...
|
PhpStorm
|
faVsco.js – CrmHelperRepository.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestv100% (C478• Thu 14 May 17:23:39QProject v© ReportController.php© AutomatedReportGenerated.php:18TrackAutomatedReportGeneratedEvent.phpPlaybackController.php• CrmObjectsO DecorateActivity> D Dummyv @ Helpers.T ActivityPlaybookTra© Arraylterator.php+ ConnectionState Tra© CrmHelperReposito© FilterJoinedParticipT OpportunitySyncab1314v D HubspotD AccountSyncStrate15› D Actions16D ContactSyncStrate!17> ODTO18› OJ Fields19› 0 Journal27Metadata28v OpportunitySyncSti> O Concerns35© HubspotLastMor© HubspotLastMor3637© HubspotLastMor© HubspotLastMor38© HubspotLastMor39© HubspotSingleS:40© HubspotSyncStr4142© HubspotWebhocv D Pagination43© HubspotPaginati49© PaginationConfig50© PaginationState.> O ProspectSearchStra• Redisv O ServiceTraits(. OnnortunitvSvnrUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.php© ActivityPlaybookTrait.php© CrmHelperRepository.php xAccountController.phpT IntegrationAppTrait.php.env.staging= .env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.phpHandleHubspotRateLimit.phpUSe/***/* A collection of DB-related internal functionalities or all CRMs.class CrmHelperRepositorypublic function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory{...}1 usagepublic function getActivityFieldValueByName(Field $activityField, string $categoryName): ?FieldValue{…}1 usagepublic function existsActivityFieldValueByName(Field $activityField, string $categoryName): boolreturn $activityField->values)l->where( column: 'Label', ScategoryName)-›exists():public function hasFeature(Activity $activity, FeatureEnum $featureName): boolf...}Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)=custom.log=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]D V234Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !M crm_layout_eilIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial.i on u.id= sa.:1..n<->1: on t.Lid = 1052 andIMaccounts wheiactivitiesUTF-8W Windsurf Teams38:40Co 4 spaces...
|
NULL
|
5406396250506849296
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestv100% (C478• Thu 14 May 17:23:39QProject v© ReportController.php© AutomatedReportGenerated.php:18TrackAutomatedReportGeneratedEvent.phpPlaybackController.php• CrmObjectsO DecorateActivity> D Dummyv @ Helpers.T ActivityPlaybookTra© Arraylterator.php+ ConnectionState Tra© CrmHelperReposito© FilterJoinedParticipT OpportunitySyncab1314v D HubspotD AccountSyncStrate15› D Actions16D ContactSyncStrate!17> ODTO18› OJ Fields19› 0 Journal27Metadata28v OpportunitySyncSti> O Concerns35© HubspotLastMor© HubspotLastMor3637© HubspotLastMor© HubspotLastMor38© HubspotLastMor39© HubspotSingleS:40© HubspotSyncStr4142© HubspotWebhocv D Pagination43© HubspotPaginati49© PaginationConfig50© PaginationState.> O ProspectSearchStra• Redisv O ServiceTraits(. OnnortunitvSvnrUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.php© ActivityPlaybookTrait.php© CrmHelperRepository.php xAccountController.phpT IntegrationAppTrait.php.env.staging= .env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.phpHandleHubspotRateLimit.phpUSe/***/* A collection of DB-related internal functionalities or all CRMs.class CrmHelperRepositorypublic function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory{...}1 usagepublic function getActivityFieldValueByName(Field $activityField, string $categoryName): ?FieldValue{…}1 usagepublic function existsActivityFieldValueByName(Field $activityField, string $categoryName): boolreturn $activityField->values)l->where( column: 'Label', ScategoryName)-›exists():public function hasFeature(Activity $activity, FeatureEnum $featureName): boolf...}Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)=custom.log=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]D V234Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !M crm_layout_eilIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial.i on u.id= sa.:1..n<->1: on t.Lid = 1052 andIMaccounts wheiactivitiesUTF-8W Windsurf Teams38:40Co 4 spaces...
|
45175
|
NULL
|
NULL
|
NULL
|
|
45175
|
1621
|
22
|
2026-05-14T14:23:35.470701+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768615470_m1.jpg...
|
PhpStorm
|
faVsco.js – CrmHelperRepository.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.054166667,"top":0.027777778,"width":0.08055556,"height":0.035555556},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.13472222,"top":0.027777778,"width":0.25555557,"height":0.035555556},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.6326389,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.6645833,"top":0.027777778,"width":0.15902779,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.82361114,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.8472222,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.87083334,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.9291667,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-5784594327568142026
|
-7196678489907033719
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestv100% (C478• Thu 14 May 17:23:35QProject v© ReportController.php© AutomatedReportGenerated.php:18TrackAutomatedReportGeneratedEvent.phpPlaybackController.php• CrmObjects• DecorateActivity> D Dummyv @ Helpers.T ActivityPlaybookTra© Arraylterator.php€ ConnectionStateTra© CrmHelperReposito© FilterJoinedParticipT OpportunitySyncab1314v D HubspotD AccountSyncStrate15› D Actions16D ContactSyncStrate!17> ODTO18› OJ Fields19› 0 Journal27Metadatav OpportunitySyncSti28> O Concerns35© HubspotLastMor© HubspotLastMor36© HubspotLastMor37© HubspotLastMor38© HubspotLastMor39© HubspotSingleS:40© HubspotSyncStr4142© HubspotWebhocv D Pagination43© HubspotPaginati49© PaginationConfig50© PaginationState.> O ProspectSearchStraRedisv O ServiceTraits(. OnnortunitvSvnrUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.php© ActivityPlaybookTrait.php© CrmHelperRepository.php xAccountController.phpT IntegrationAppTrait.php.env.staging= .env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.phpHandleHubspotRateLimit.phpUSe/***/* A collection of DB-related internal functionalities or all CRMs.class CrmHelperRepositorypublic function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory{...}1 usagepublic function getActivityFieldValueByName(Field $activityField, string $categoryName): ?FieldValue{…}1 usagepublic function existsActivityFieldValueByName(Field SactivityField, string $categoryName): boolreturn $activityField->values()->whSactivityField: Field->exSource: .../app/Services/Crm/Helpers/CrmHelperRepository.phppublic funct0 :reEnum $featureName): boolf...}Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)=custom.log=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]D V234Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial.1 on u.id= sa.:1..n<->1: on t.Lid = 1052 andIMaccounts wheiactivities36:21UTF-8W Windsurf TeamsCo 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45174
|
1622
|
12
|
2026-05-14T14:23:35.799112+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768615799_m2.jpg...
|
PhpStorm
|
faVsco.js – CrmHelperRepository.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Helpers;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Playbook;
use Jiminny\Models\PlaybookCategory;
/**
* A collection of DB-related internal functionalities or all CRMs.
*/
class CrmHelperRepository
{
public function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory
{
/** @var ?PlaybookCategory */
return $playbook->categories()
->where('name', trim($categoryName))
->orderBy('id', 'desc')
->first();
}
public function getActivityFieldValueByName(Field $activityField, string $categoryName): ?FieldValue
{
/** @var ?FieldValue */
return $activityField->values()
->where('label', $categoryName)
->first();
}
public function existsActivityFieldValueByName(Field $activityField, string $categoryName): bool
{
return $activityField->values()
->where('label', $categoryName)
->exists();
}
public function hasFeature(Activity $activity, FeatureEnum $featureName): bool
{
return $activity->getUser()
->getTeam()
->hasFeature($featureName);
}
}
Execute...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.2962101,"top":1.0,"width":0.03856383,"height":-0.019952059},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.33477393,"top":1.0,"width":0.122340426,"height":-0.019952059},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.5731383,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.5884308,"top":1.0,"width":0.076130316,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.66456115,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.67586434,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.6871675,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.7150931,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.72639626,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.73769945,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Helpers;\n\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\PlaybookCategory;\n\n/**\n * A collection of DB-related internal functionalities or all CRMs.\n */\nclass CrmHelperRepository\n{\n public function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory\n {\n /** @var ?PlaybookCategory */\n return $playbook->categories()\n ->where('name', trim($categoryName))\n ->orderBy('id', 'desc')\n ->first();\n }\n\n public function getActivityFieldValueByName(Field $activityField, string $categoryName): ?FieldValue\n {\n /** @var ?FieldValue */\n return $activityField->values()\n ->where('label', $categoryName)\n ->first();\n }\n\n public function existsActivityFieldValueByName(Field $activityField, string $categoryName): bool\n {\n return $activityField->values()\n ->where('label', $categoryName)\n ->exists();\n }\n\n public function hasFeature(Activity $activity, FeatureEnum $featureName): bool\n {\n return $activity->getUser()\n ->getTeam()\n ->hasFeature($featureName);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Helpers;\n\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\PlaybookCategory;\n\n/**\n * A collection of DB-related internal functionalities or all CRMs.\n */\nclass CrmHelperRepository\n{\n public function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory\n {\n /** @var ?PlaybookCategory */\n return $playbook->categories()\n ->where('name', trim($categoryName))\n ->orderBy('id', 'desc')\n ->first();\n }\n\n public function getActivityFieldValueByName(Field $activityField, string $categoryName): ?FieldValue\n {\n /** @var ?FieldValue */\n return $activityField->values()\n ->where('label', $categoryName)\n ->first();\n }\n\n public function existsActivityFieldValueByName(Field $activityField, string $categoryName): bool\n {\n return $activityField->values()\n ->where('label', $categoryName)\n ->exists();\n }\n\n public function hasFeature(Activity $activity, FeatureEnum $featureName): bool\n {\n return $activity->getUser()\n ->getTeam()\n ->hasFeature($featureName);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-3489503532064552681
|
-8168608824874202789
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Helpers;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Playbook;
use Jiminny\Models\PlaybookCategory;
/**
* A collection of DB-related internal functionalities or all CRMs.
*/
class CrmHelperRepository
{
public function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory
{
/** @var ?PlaybookCategory */
return $playbook->categories()
->where('name', trim($categoryName))
->orderBy('id', 'desc')
->first();
}
public function getActivityFieldValueByName(Field $activityField, string $categoryName): ?FieldValue
{
/** @var ?FieldValue */
return $activityField->values()
->where('label', $categoryName)
->first();
}
public function existsActivityFieldValueByName(Field $activityField, string $categoryName): bool
{
return $activityField->values()
->where('label', $categoryName)
->exists();
}
public function hasFeature(Activity $activity, FeatureEnum $featureName): bool
{
return $activity->getUser()
->getTeam()
->hasFeature($featureName);
}
}
Execute...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45173
|
1622
|
11
|
2026-05-14T14:23:29.536165+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768609536_m2.jpg...
|
PhpStorm
|
faVsco.js – ActivityPlaybookTrait.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.2962101,"top":1.0,"width":0.03856383,"height":-0.019952059},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.33477393,"top":1.0,"width":0.122340426,"height":-0.019952059},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.5731383,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.5884308,"top":1.0,"width":0.076130316,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.66456115,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7759925082980464890
|
-7195274138718106135
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterdav at 13.33Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:31Yesterday at 13:30Yesterdav at 13:30Yesterday at 13:29Yesterday at 13.28Yesterday at 13:28resterday at 15.21Yesterdav at 13:26Yesterday at 13:26Yesterday at 13:25Yesterday at 13:23Yesterday at 13:24resterday at 13-43Yesterdav at 13:22Yesterday at 13:20Yesterday at 13:20Yesterday at 13.19Yesterdav at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.15Yecterdav at 12:15Yesterday at 13:14Yesterday at 13-14Yesterdav at 13:13Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:11Yesterday at 13:10Yesterdav at 13:10Yesterday at 13:09Yesterday at 13:08Yoctorday at 12:09Yesterday at 13.0/Yocterdav at 13:06Yesterday at 13:06Yesterdav at 13:05MPEG-4 movie12 KBMPEG-4 movie9 KBMPEG-4 movieMPEG-4 movie8 KE37 KB10 KBMPEG-4 movie7 K:8 KBMPEG-4 movie9 KBMPEG-4 movie72 KBMPEG-4 movie14 KB15 KbMPEG-4 movie9 K:18 KBMPEG-4 movie12 KB10 K:16 KRIMPEG-4 movieMPEG-4 movie6 KBMPEG-4 movie12 KE23 KBMPEG-4 movie8 KB6 KB1MPEG-4 movie6 KBMPEG-4 movie11 KB11 KBMPEG-4 movie20 KEMPEG-4 movie34 KBMPEG-4 movie10 KB7K:MPEG-4 movie5 KBMPEG-4 movie11 KB26 KBMPEG-4 movie111 KPMPEG-4 movie102 KBMPEG-4 movie88 KB59 K:MPEG-4 movie98 KBMPEG-4 movie97 KB66 KBЛAKEMPEG-4 movieMDEG-A movie93 KB78 KBMPEG-4 movie50 K:MPEG-A movid58 KB MPEG-4 movie27 KB7 KB112 KрMPEG-4 movieMPEG-4 movie32 KB17 KBMPEG-4 movie19 Kг32 KBMPEG-4 movie10 KB24 K8MPEG-4 movieFavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-ywJo.ziPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dma- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.63 GB availabld• Inu 14 May 1/.23.49Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
45171
|
NULL
|
NULL
|
NULL
|
|
45172
|
1621
|
21
|
2026-05-14T14:23:29.568203+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768609568_m1.jpg...
|
PhpStorm
|
faVsco.js – ActivityPlaybookTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStorm•FileEditViewNavigateCodeLaravelRefactorRu PhpStorm•FileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% CFV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestv8• Thu 14 May 17:23:29* :QProject v© ReportController.php© AutomatedReportGenerated.php:= custom.log18TrackAutomatedReportGeneratedEvent.phpPlaybackController.php> D CrmObjects• DecorateActivity> D Dummyv D Helpers.T, ActivityPlaybookTra© Arraylterator.php+ ConnectionState Tra© CrmHelperReposito17© FilterJoinedParticip32T OpportunitySyncab33v D Hubspot39D AccountSyncStrate40› D Actions44D ContactSyncStrate! 45> ODTO46› OJ Fields47› Journal48Metadata49v OpportunitySyncSti50> O Concerns51© HubspotLastMor52© HubspotLastMor53© HubspotLastMor54© HubspotLastMor55© HubspotLastMor56© HubspotSingleS:57© HubspotSyncStr58© HubspotWebhoc59v D Pagination60© HubspotPaginati 61© PaginationConfig 79© PaginationState.80> O ProspectSearchStra• Redisv O ServiceTraits(. OnnortunitvSvnrUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php=laravel.log• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.phpT ActivityPlaybookTrait.php xSF [jiminny@localhost]© AccountController.phpIntegrationAppTrait.php.env.staging.envDetachActivityObject.phpA HS_local [jiminny@localho:WRematchActivityOnCrmObjectDetach.phpMatchActivityCrmData.php© Client.php© HubspotPaginationService.php4 console [QAI PROD] XHandleHubspotRateLimit.phptrait ActivityPlaybookTrait*/4 console [PROD]A console (EU]protected function getPlaybook(User Suser): ?Playbook{...}protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory{...}public function matchesCrmType(PlaybookCategory $category): bool$playbook = Scategory->getPlaybookO:if ($playbook === null) {return false;SactivityField = $playbook->getActivityField();if (SactivityField === null) {return false;// Check the field values for a matching option.return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());public function getCrmType(?PlaybookCategory $category): ?FieldValuel...}D V234Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASE WHEN,id FROM social,1 on u.id= sa.:1..n<->1: on t.L_id = 1052 andIMaccounts wheiactivitiesWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams58:53UTF-8Co 4 spaces...
|
NULL
|
2668727136616592203
|
NULL
|
click
|
ocr
|
NULL
|
PhpStorm•FileEditViewNavigateCodeLaravelRefactorRu PhpStorm•FileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% CFV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestv8• Thu 14 May 17:23:29* :QProject v© ReportController.php© AutomatedReportGenerated.php:= custom.log18TrackAutomatedReportGeneratedEvent.phpPlaybackController.php> D CrmObjects• DecorateActivity> D Dummyv D Helpers.T, ActivityPlaybookTra© Arraylterator.php+ ConnectionState Tra© CrmHelperReposito17© FilterJoinedParticip32T OpportunitySyncab33v D Hubspot39D AccountSyncStrate40› D Actions44D ContactSyncStrate! 45> ODTO46› OJ Fields47› Journal48Metadata49v OpportunitySyncSti50> O Concerns51© HubspotLastMor52© HubspotLastMor53© HubspotLastMor54© HubspotLastMor55© HubspotLastMor56© HubspotSingleS:57© HubspotSyncStr58© HubspotWebhoc59v D Pagination60© HubspotPaginati 61© PaginationConfig 79© PaginationState.80> O ProspectSearchStra• Redisv O ServiceTraits(. OnnortunitvSvnrUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php=laravel.log• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.phpT ActivityPlaybookTrait.php xSF [jiminny@localhost]© AccountController.phpIntegrationAppTrait.php.env.staging.envDetachActivityObject.phpA HS_local [jiminny@localho:WRematchActivityOnCrmObjectDetach.phpMatchActivityCrmData.php© Client.php© HubspotPaginationService.php4 console [QAI PROD] XHandleHubspotRateLimit.phptrait ActivityPlaybookTrait*/4 console [PROD]A console (EU]protected function getPlaybook(User Suser): ?Playbook{...}protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory{...}public function matchesCrmType(PlaybookCategory $category): bool$playbook = Scategory->getPlaybookO:if ($playbook === null) {return false;SactivityField = $playbook->getActivityField();if (SactivityField === null) {return false;// Check the field values for a matching option.return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());public function getCrmType(?PlaybookCategory $category): ?FieldValuel...}D V234Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASE WHEN,id FROM social,1 on u.id= sa.:1..n<->1: on t.L_id = 1052 andIMaccounts wheiactivitiesWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams58:53UTF-8Co 4 spaces...
|
45170
|
NULL
|
NULL
|
NULL
|
|
45171
|
1622
|
10
|
2026-05-14T14:23:25.877873+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768605877_m2.jpg...
|
PhpStorm
|
faVsco.js – ActivityPlaybookTrait.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Helpers;
use Jiminny\Integrations\PlaybookResolver;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\Playbook;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Models\User;
/**
* Playbook related methods commonly used in all CRMs.
*/
trait ActivityPlaybookTrait
{
protected CrmHelperRepository $crmHelperRepository;
public function getPlaybookFromActivity(Activity $activity): ?Playbook
{
if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {
return $activity->getActivityType()->getPlaybook();
}
return $this->getPlaybook($activity->getUser());
}
/**
* Gets the playbook for the user
*/
protected function getPlaybook(User $user): ?Playbook
{
$playbookResolver = app(PlaybookResolver::class);
return $playbookResolver->resolvePlaybookByUser($user);
}
protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory
{
return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);
}
public function matchesCrmType(PlaybookCategory $category): bool
{
$playbook = $category->getPlaybook();
if ($playbook === null) {
return false;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return false;
}
// Check the field values for a matching option.
return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());
}
public function getCrmType(?PlaybookCategory $category): ?FieldValue
{
if ($category === null) {
return null;
}
$playbook = $category->getPlaybook();
if ($playbook === null) {
return null;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return null;
}
return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.2962101,"top":1.0,"width":0.03856383,"height":-0.019952059},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.33477393,"top":1.0,"width":0.122340426,"height":-0.019952059},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.5731383,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.5884308,"top":1.0,"width":0.076130316,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.66456115,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.67586434,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.6871675,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.7150931,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.72639626,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.73769945,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Helpers;\n\nuse Jiminny\\Integrations\\PlaybookResolver;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Models\\User;\n\n/**\n * Playbook related methods commonly used in all CRMs.\n */\ntrait ActivityPlaybookTrait\n{\n protected CrmHelperRepository $crmHelperRepository;\n\n public function getPlaybookFromActivity(Activity $activity): ?Playbook\n {\n if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {\n return $activity->getActivityType()->getPlaybook();\n }\n\n return $this->getPlaybook($activity->getUser());\n }\n\n /**\n * Gets the playbook for the user\n */\n protected function getPlaybook(User $user): ?Playbook\n {\n $playbookResolver = app(PlaybookResolver::class);\n\n return $playbookResolver->resolvePlaybookByUser($user);\n }\n\n protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory\n {\n return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);\n }\n\n public function matchesCrmType(PlaybookCategory $category): bool\n {\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return false;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return false;\n }\n\n // Check the field values for a matching option.\n return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());\n }\n\n public function getCrmType(?PlaybookCategory $category): ?FieldValue\n {\n if ($category === null) {\n return null;\n }\n\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return null;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return null;\n }\n\n return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());\n }\n}","depth":4,"bounds":{"left":0.3899601,"top":0.8667199,"width":0.29787233,"height":0.1332801},"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Helpers;\n\nuse Jiminny\\Integrations\\PlaybookResolver;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Models\\User;\n\n/**\n * Playbook related methods commonly used in all CRMs.\n */\ntrait ActivityPlaybookTrait\n{\n protected CrmHelperRepository $crmHelperRepository;\n\n public function getPlaybookFromActivity(Activity $activity): ?Playbook\n {\n if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {\n return $activity->getActivityType()->getPlaybook();\n }\n\n return $this->getPlaybook($activity->getUser());\n }\n\n /**\n * Gets the playbook for the user\n */\n protected function getPlaybook(User $user): ?Playbook\n {\n $playbookResolver = app(PlaybookResolver::class);\n\n return $playbookResolver->resolvePlaybookByUser($user);\n }\n\n protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory\n {\n return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);\n }\n\n public function matchesCrmType(PlaybookCategory $category): bool\n {\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return false;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return false;\n }\n\n // Check the field values for a matching option.\n return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());\n }\n\n public function getCrmType(?PlaybookCategory $category): ?FieldValue\n {\n if ($category === null) {\n return null;\n }\n\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return null;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return null;\n }\n\n return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false}]...
|
5486440281962872685
|
-27547832286463784
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Helpers;
use Jiminny\Integrations\PlaybookResolver;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\Playbook;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Models\User;
/**
* Playbook related methods commonly used in all CRMs.
*/
trait ActivityPlaybookTrait
{
protected CrmHelperRepository $crmHelperRepository;
public function getPlaybookFromActivity(Activity $activity): ?Playbook
{
if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {
return $activity->getActivityType()->getPlaybook();
}
return $this->getPlaybook($activity->getUser());
}
/**
* Gets the playbook for the user
*/
protected function getPlaybook(User $user): ?Playbook
{
$playbookResolver = app(PlaybookResolver::class);
return $playbookResolver->resolvePlaybookByUser($user);
}
protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory
{
return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);
}
public function matchesCrmType(PlaybookCategory $category): bool
{
$playbook = $category->getPlaybook();
if ($playbook === null) {
return false;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return false;
}
// Check the field values for a matching option.
return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());
}
public function getCrmType(?PlaybookCategory $category): ?FieldValue
{
if ($category === null) {
return null;
}
$playbook = $category->getPlaybook();
if ($playbook === null) {
return null;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return null;
}
return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());
}
}...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45170
|
1621
|
20
|
2026-05-14T14:23:25.855940+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768605855_m1.jpg...
|
PhpStorm
|
faVsco.js – ActivityPlaybookTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Helpers;
use Jiminny\Integrations\PlaybookResolver;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\Playbook;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Models\User;
/**
* Playbook related methods commonly used in all CRMs.
*/
trait ActivityPlaybookTrait
{
protected CrmHelperRepository $crmHelperRepository;
public function getPlaybookFromActivity(Activity $activity): ?Playbook
{
if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {
return $activity->getActivityType()->getPlaybook();
}
return $this->getPlaybook($activity->getUser());
}
/**
* Gets the playbook for the user
*/
protected function getPlaybook(User $user): ?Playbook
{
$playbookResolver = app(PlaybookResolver::class);
return $playbookResolver->resolvePlaybookByUser($user);
}
protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory
{
return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);
}
public function matchesCrmType(PlaybookCategory $category): bool
{
$playbook = $category->getPlaybook();
if ($playbook === null) {
return false;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return false;
}
// Check the field values for a matching option.
return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());
}
public function getCrmType(?PlaybookCategory $category): ?FieldValue
{
if ($category === null) {
return null;
}
$playbook = $category->getPlaybook();
if ($playbook === null) {
return null;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return null;
}
return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide
app ~/jiminny/app
.circleci
.cursor
.github
.sonarlint
.vscode
.windsurf
app, sources root
Actions
Component
Acl
ActionItems
Activity
ActivityAnalytics
ActivitySearch
AiActivityType...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.054166667,"top":0.027777778,"width":0.08055556,"height":0.035555556},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.13472222,"top":0.027777778,"width":0.25555557,"height":0.035555556},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.6326389,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.6645833,"top":0.027777778,"width":0.15902779,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.82361114,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.8472222,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.87083334,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.9291667,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9527778,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9763889,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Helpers;\n\nuse Jiminny\\Integrations\\PlaybookResolver;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Models\\User;\n\n/**\n * Playbook related methods commonly used in all CRMs.\n */\ntrait ActivityPlaybookTrait\n{\n protected CrmHelperRepository $crmHelperRepository;\n\n public function getPlaybookFromActivity(Activity $activity): ?Playbook\n {\n if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {\n return $activity->getActivityType()->getPlaybook();\n }\n\n return $this->getPlaybook($activity->getUser());\n }\n\n /**\n * Gets the playbook for the user\n */\n protected function getPlaybook(User $user): ?Playbook\n {\n $playbookResolver = app(PlaybookResolver::class);\n\n return $playbookResolver->resolvePlaybookByUser($user);\n }\n\n protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory\n {\n return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);\n }\n\n public function matchesCrmType(PlaybookCategory $category): bool\n {\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return false;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return false;\n }\n\n // Check the field values for a matching option.\n return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());\n }\n\n public function getCrmType(?PlaybookCategory $category): ?FieldValue\n {\n if ($category === null) {\n return null;\n }\n\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return null;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return null;\n }\n\n return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Helpers;\n\nuse Jiminny\\Integrations\\PlaybookResolver;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Models\\User;\n\n/**\n * Playbook related methods commonly used in all CRMs.\n */\ntrait ActivityPlaybookTrait\n{\n protected CrmHelperRepository $crmHelperRepository;\n\n public function getPlaybookFromActivity(Activity $activity): ?Playbook\n {\n if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {\n return $activity->getActivityType()->getPlaybook();\n }\n\n return $this->getPlaybook($activity->getUser());\n }\n\n /**\n * Gets the playbook for the user\n */\n protected function getPlaybook(User $user): ?Playbook\n {\n $playbookResolver = app(PlaybookResolver::class);\n\n return $playbookResolver->resolvePlaybookByUser($user);\n }\n\n protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory\n {\n return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);\n }\n\n public function matchesCrmType(PlaybookCategory $category): bool\n {\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return false;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return false;\n }\n\n // Check the field values for a matching option.\n return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());\n }\n\n public function getCrmType(?PlaybookCategory $category): ?FieldValue\n {\n if ($category === null) {\n return null;\n }\n\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return null;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return null;\n }\n\n return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.85486114,"top":0.31,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.87291664,"top":0.31,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.9138889,"top":0.31,"width":0.059027776,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"bounds":{"left":0.8645833,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.8854167,"top":0.34444445,"width":0.015277778,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.9048611,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"4","depth":4,"bounds":{"left":0.92569447,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.9458333,"top":0.3422222,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.9611111,"top":0.3422222,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","depth":4,"on_screen":true,"value":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.025,"top":0.06666667,"width":0.050694443,"height":0.034444444},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"app ~/jiminny/app","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":".circleci","depth":7,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":".cursor","depth":7,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":".github","depth":7,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":".sonarlint","depth":7,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":".vscode","depth":7,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":".windsurf","depth":7,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"app, sources root","depth":7,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Actions","depth":8,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Component","depth":8,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Acl","depth":9,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ActionItems","depth":9,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"Activity","depth":9,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ActivityAnalytics","depth":9,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ActivitySearch","depth":9,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"AiActivityType","depth":9,"on_screen":false,"role_description":"text"}]...
|
-7840118185622920921
|
6758386328208093789
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Helpers;
use Jiminny\Integrations\PlaybookResolver;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\Playbook;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Models\User;
/**
* Playbook related methods commonly used in all CRMs.
*/
trait ActivityPlaybookTrait
{
protected CrmHelperRepository $crmHelperRepository;
public function getPlaybookFromActivity(Activity $activity): ?Playbook
{
if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {
return $activity->getActivityType()->getPlaybook();
}
return $this->getPlaybook($activity->getUser());
}
/**
* Gets the playbook for the user
*/
protected function getPlaybook(User $user): ?Playbook
{
$playbookResolver = app(PlaybookResolver::class);
return $playbookResolver->resolvePlaybookByUser($user);
}
protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory
{
return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);
}
public function matchesCrmType(PlaybookCategory $category): bool
{
$playbook = $category->getPlaybook();
if ($playbook === null) {
return false;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return false;
}
// Check the field values for a matching option.
return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());
}
public function getCrmType(?PlaybookCategory $category): ?FieldValue
{
if ($category === null) {
return null;
}
$playbook = $category->getPlaybook();
if ($playbook === null) {
return null;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return null;
}
return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide
app ~/jiminny/app
.circleci
.cursor
.github
.sonarlint
.vscode
.windsurf
app, sources root
Actions
Component
Acl
ActionItems
Activity
ActivityAnalytics
ActivitySearch
AiActivityType...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45169
|
1621
|
19
|
2026-05-14T14:23:22.596619+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768602596_m1.jpg...
|
PhpStorm
|
faVsco.js – ActivityPlaybookTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% <7•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestv8• Thu 14 May 17:23:22* :QProject v© ReportController.php© AutomatedReportGenerated.php:= custom.logTrackAutomatedReportGeneratedEvent.phpPlaybackController.php> D CrmObjectsUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php© SendReportJob.php=laravel.logO DecorateActivity› D Dummy© DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.phpT ActivityPlaybookTrait.php xSF [jiminny@localhost]v D Helpers.© AccountController.phpIntegrationAppTrait.php.env.staging.env© DetachActivityObject.phpA HS_local [jiminny@localho:WT, ActivityPlaybookTraRematchActivityOnCrmObjectDetach.phpMatchActivityCrmData.php© Client.php© HubspotPaginationService.php4 console [QAI PROD] X18© Arraylterator.php+ ConnectionState Tra© CrmHelperReposito17© FilterJoinedParticipHandleHubspotRateLimit.phptrait ActivityPlaybookTrait8 usages4 console [PROD]A console (EU]T OpportunitySyncab 19protected CrmHelperRepository $crmHelperRepository;v D Hubspot20D AccountSyncStrate21public function getPlaybookFromActivity(Activity Sactivity): ?Playbook{...}› D Actions29D ContactSyncStrate!30> ODTO31› OJ Fields32/***/* Gets the playbook for the user› D Journal33protected function getPlaybook(User $user): ?Playbook{... }Metadata39OpportunitySyncStiprotected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory{..}> O Concerns44© HubspotLastMor45public function matchesCrmType(PlaybookCategory $category): bool© HubspotLastMor46© HubspotLastMor47$playbook = $category->getPlaybook() :||Cascade 28 XlCommand &81© HubspotLastMor 48© HubspotLastMor49return talse;© HubspotSingleS:50© HubspotSyncStr 51© HubspotWebhoc 52v D Pagination53© HubspotPaginati 54SactivityField = $playbook->getActivityField:if ($activityField === null) {return false;© PaginationConfig 55© PaginationState.56> O ProspectSearchStra• Redis58// Check the field values for a matching option.return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName()) 233 vv O ServiceTraits59D Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;team_feature:m opportunitie:teams:1.id, CASE WHENidFROMsocial.on u.id= sa.:1..n<->1: on t._id = 1052 andIMaccounts wheiactivities(). OnnortunitvSunr 4AWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams47:46 (37 chars)UTF-8C 4 spaces...
|
NULL
|
6828021430120088485
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% <7•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestv8• Thu 14 May 17:23:22* :QProject v© ReportController.php© AutomatedReportGenerated.php:= custom.logTrackAutomatedReportGeneratedEvent.phpPlaybackController.php> D CrmObjectsUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php© SendReportJob.php=laravel.logO DecorateActivity› D Dummy© DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.phpT ActivityPlaybookTrait.php xSF [jiminny@localhost]v D Helpers.© AccountController.phpIntegrationAppTrait.php.env.staging.env© DetachActivityObject.phpA HS_local [jiminny@localho:WT, ActivityPlaybookTraRematchActivityOnCrmObjectDetach.phpMatchActivityCrmData.php© Client.php© HubspotPaginationService.php4 console [QAI PROD] X18© Arraylterator.php+ ConnectionState Tra© CrmHelperReposito17© FilterJoinedParticipHandleHubspotRateLimit.phptrait ActivityPlaybookTrait8 usages4 console [PROD]A console (EU]T OpportunitySyncab 19protected CrmHelperRepository $crmHelperRepository;v D Hubspot20D AccountSyncStrate21public function getPlaybookFromActivity(Activity Sactivity): ?Playbook{...}› D Actions29D ContactSyncStrate!30> ODTO31› OJ Fields32/***/* Gets the playbook for the user› D Journal33protected function getPlaybook(User $user): ?Playbook{... }Metadata39OpportunitySyncStiprotected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory{..}> O Concerns44© HubspotLastMor45public function matchesCrmType(PlaybookCategory $category): bool© HubspotLastMor46© HubspotLastMor47$playbook = $category->getPlaybook() :||Cascade 28 XlCommand &81© HubspotLastMor 48© HubspotLastMor49return talse;© HubspotSingleS:50© HubspotSyncStr 51© HubspotWebhoc 52v D Pagination53© HubspotPaginati 54SactivityField = $playbook->getActivityField:if ($activityField === null) {return false;© PaginationConfig 55© PaginationState.56> O ProspectSearchStra• Redis58// Check the field values for a matching option.return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName()) 233 vv O ServiceTraits59D Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;team_feature:m opportunitie:teams:1.id, CASE WHENidFROMsocial.on u.id= sa.:1..n<->1: on t._id = 1052 andIMaccounts wheiactivities(). OnnortunitvSunr 4AWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams47:46 (37 chars)UTF-8C 4 spaces...
|
45166
|
NULL
|
NULL
|
NULL
|
|
45168
|
1622
|
9
|
2026-05-14T14:23:24.414752+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768604414_m2.jpg...
|
PhpStorm
|
faVsco.js – ActivityPlaybookTrait.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Helpers;
use Jiminny\Integrations\PlaybookResolver;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\Playbook;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Models\User;
/**
* Playbook related methods commonly used in all CRMs.
*/
trait ActivityPlaybookTrait
{
protected CrmHelperRepository $crmHelperRepository;
public function getPlaybookFromActivity(Activity $activity): ?Playbook
{
if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {
return $activity->getActivityType()->getPlaybook();
}
return $this->getPlaybook($activity->getUser());
}
/**
* Gets the playbook for the user
*/
protected function getPlaybook(User $user): ?Playbook
{
$playbookResolver = app(PlaybookResolver::class);
return $playbookResolver->resolvePlaybookByUser($user);
}
protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory
{
return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);
}
public function matchesCrmType(PlaybookCategory $category): bool
{
$playbook = $category->getPlaybook();
if ($playbook === null) {
return false;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return false;
}
// Check the field values for a matching option.
return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());
}
public function getCrmType(?PlaybookCategory $category): ?FieldValue
{
if ($category === null) {
return null;
}
$playbook = $category->getPlaybook();
if ($playbook === null) {
return null;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return null;
}
return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.2962101,"top":1.0,"width":0.03856383,"height":-0.019952059},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.33477393,"top":1.0,"width":0.122340426,"height":-0.019952059},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.5731383,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.5884308,"top":1.0,"width":0.076130316,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.66456115,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.67586434,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.6871675,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.7150931,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.72639626,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.73769945,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Helpers;\n\nuse Jiminny\\Integrations\\PlaybookResolver;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Models\\User;\n\n/**\n * Playbook related methods commonly used in all CRMs.\n */\ntrait ActivityPlaybookTrait\n{\n protected CrmHelperRepository $crmHelperRepository;\n\n public function getPlaybookFromActivity(Activity $activity): ?Playbook\n {\n if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {\n return $activity->getActivityType()->getPlaybook();\n }\n\n return $this->getPlaybook($activity->getUser());\n }\n\n /**\n * Gets the playbook for the user\n */\n protected function getPlaybook(User $user): ?Playbook\n {\n $playbookResolver = app(PlaybookResolver::class);\n\n return $playbookResolver->resolvePlaybookByUser($user);\n }\n\n protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory\n {\n return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);\n }\n\n public function matchesCrmType(PlaybookCategory $category): bool\n {\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return false;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return false;\n }\n\n // Check the field values for a matching option.\n return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());\n }\n\n public function getCrmType(?PlaybookCategory $category): ?FieldValue\n {\n if ($category === null) {\n return null;\n }\n\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return null;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return null;\n }\n\n return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());\n }\n}","depth":4,"bounds":{"left":0.3899601,"top":0.8667199,"width":0.29787233,"height":0.1332801},"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Helpers;\n\nuse Jiminny\\Integrations\\PlaybookResolver;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Models\\User;\n\n/**\n * Playbook related methods commonly used in all CRMs.\n */\ntrait ActivityPlaybookTrait\n{\n protected CrmHelperRepository $crmHelperRepository;\n\n public function getPlaybookFromActivity(Activity $activity): ?Playbook\n {\n if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {\n return $activity->getActivityType()->getPlaybook();\n }\n\n return $this->getPlaybook($activity->getUser());\n }\n\n /**\n * Gets the playbook for the user\n */\n protected function getPlaybook(User $user): ?Playbook\n {\n $playbookResolver = app(PlaybookResolver::class);\n\n return $playbookResolver->resolvePlaybookByUser($user);\n }\n\n protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory\n {\n return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);\n }\n\n public function matchesCrmType(PlaybookCategory $category): bool\n {\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return false;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return false;\n }\n\n // Check the field values for a matching option.\n return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());\n }\n\n public function getCrmType(?PlaybookCategory $category): ?FieldValue\n {\n if ($category === null) {\n return null;\n }\n\n $playbook = $category->getPlaybook();\n if ($playbook === null) {\n return null;\n }\n\n $activityField = $playbook->getActivityField();\n if ($activityField === null) {\n return null;\n }\n\n return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":false,"is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-5562972003945315574
|
-1468682120858978166
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Helpers;
use Jiminny\Integrations\PlaybookResolver;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\Playbook;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Models\User;
/**
* Playbook related methods commonly used in all CRMs.
*/
trait ActivityPlaybookTrait
{
protected CrmHelperRepository $crmHelperRepository;
public function getPlaybookFromActivity(Activity $activity): ?Playbook
{
if ($activity->hasActivityType() && $activity->getActivityType()->hasPlaybook()) {
return $activity->getActivityType()->getPlaybook();
}
return $this->getPlaybook($activity->getUser());
}
/**
* Gets the playbook for the user
*/
protected function getPlaybook(User $user): ?Playbook
{
$playbookResolver = app(PlaybookResolver::class);
return $playbookResolver->resolvePlaybookByUser($user);
}
protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory
{
return $this->crmHelperRepository->getPlaybookCategory($playbook, $categoryName);
}
public function matchesCrmType(PlaybookCategory $category): bool
{
$playbook = $category->getPlaybook();
if ($playbook === null) {
return false;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return false;
}
// Check the field values for a matching option.
return $this->crmHelperRepository->existsActivityFieldValueByName($activityField, $category->getName());
}
public function getCrmType(?PlaybookCategory $category): ?FieldValue
{
if ($category === null) {
return null;
}
$playbook = $category->getPlaybook();
if ($playbook === null) {
return null;
}
$activityField = $playbook->getActivityField();
if ($activityField === null) {
return null;
}
return $this->crmHelperRepository->getActivityFieldValueByName($activityField, $category->getName());
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results...
|
45167
|
NULL
|
NULL
|
NULL
|
|
45167
|
1622
|
8
|
2026-05-14T14:23:20.679248+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768600679_m2.jpg...
|
PhpStorm
|
faVsco.js – ActivityPlaybookTrait.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterdav at 13.35Yesterday at 13:34Yesterday at 13.33Yesterdav at 13:33Yesterday at 13:32Yesterday at 13:32Yesterday at 13:31Yesterday at 13.30Yesterday at 13:29Yesterday at 13:29resterday at 15.2oYesterdav at 13:28Yesterday at 13:27Yesterday at 13:26Yesterday at 13:26resterday at 13-40Yesterdav at 13:24Yesterday at 13:24Yesterday at 13:23Yesterday at 13.20Yesterdav at 13:20Yesterday at 13:19Yesterday at 13:19Yesterday at 13:18Yesterday at 13:18Yesterday at 13.17Yecterdav at 12:16Yesterday at 13:16Yesterday at 13.10Yesterdav at 13:15Yesterday at 13:14Yesterday at 13:13Yecterdav at 12:12Yesterday at 13:12Yesterday at 13.12Yesterdav at 13:11Yesterday at 13:11Yesterday at 13:10Yesterday at 13:09Yesterday at 13:09Yesterday at 13.08Yocterdav at 12:08Yesterday at 13:07Yesterdav at 13:0616 K:MPEG-4 movie17 KBMPEG-4 movie29 KBMPEG-4 movieMPEG-4 movie12 KE9 KBMPE0"4 movie8 K:37 KBMPEG-4 movie10 KBIKBnMP2G-4 movie8 KBMPEG-4 movie9 KB8 KBMPEG-4 movie72 K:14 KBMPEG-4 movie13 KBMPEG-4 movie18 KBMPEG-4 movie12 KB10 KBMPEG-4 movie16 KEMPEG-4 movie6 KB MPEG-4 movie6 KB12 KB|MPEG-4 movie23 KBMPEG-4 movieMPEG-4 movie6KEMPEG-4 movie11 KBMPEG-4 movie11 KBMPEG-4 movie20 K:MPEG-4 movie34 KBMPEG-4 movie10 KB7 KBMPEG-4 movie5KPMPEG-4 movie11 KBMPEG-4 movie26 KBMPEG-4 movie111 K:MPEG-4 movie102 KBMPEG-4 movie88 KB59 KBO9 KRMPEG-4 movieMDEG-A movie97 KB66 KBMPEG-4 movie44K:MPSG-A movid93 KBMPEG-4 movie78 KB50 KB59 KPMPEG-4 movieMPEG-4 movie27 KBMPEG-4 movie12 K:32 KBMPEG-4 movie17 KB19K8MPEG-4 movie• 0FavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-yWJo.zioPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dmaimage.jpg- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.jsonm licence bettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pa• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.63 GB availabld• Inu 14 May 1/.23.20Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
-3609530195320133031
|
NULL
|
click
|
ocr
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterdav at 13.35Yesterday at 13:34Yesterday at 13.33Yesterdav at 13:33Yesterday at 13:32Yesterday at 13:32Yesterday at 13:31Yesterday at 13.30Yesterday at 13:29Yesterday at 13:29resterday at 15.2oYesterdav at 13:28Yesterday at 13:27Yesterday at 13:26Yesterday at 13:26resterday at 13-40Yesterdav at 13:24Yesterday at 13:24Yesterday at 13:23Yesterday at 13.20Yesterdav at 13:20Yesterday at 13:19Yesterday at 13:19Yesterday at 13:18Yesterday at 13:18Yesterday at 13.17Yecterdav at 12:16Yesterday at 13:16Yesterday at 13.10Yesterdav at 13:15Yesterday at 13:14Yesterday at 13:13Yecterdav at 12:12Yesterday at 13:12Yesterday at 13.12Yesterdav at 13:11Yesterday at 13:11Yesterday at 13:10Yesterday at 13:09Yesterday at 13:09Yesterday at 13.08Yocterdav at 12:08Yesterday at 13:07Yesterdav at 13:0616 K:MPEG-4 movie17 KBMPEG-4 movie29 KBMPEG-4 movieMPEG-4 movie12 KE9 KBMPE0"4 movie8 K:37 KBMPEG-4 movie10 KBIKBnMP2G-4 movie8 KBMPEG-4 movie9 KB8 KBMPEG-4 movie72 K:14 KBMPEG-4 movie13 KBMPEG-4 movie18 KBMPEG-4 movie12 KB10 KBMPEG-4 movie16 KEMPEG-4 movie6 KB MPEG-4 movie6 KB12 KB|MPEG-4 movie23 KBMPEG-4 movieMPEG-4 movie6KEMPEG-4 movie11 KBMPEG-4 movie11 KBMPEG-4 movie20 K:MPEG-4 movie34 KBMPEG-4 movie10 KB7 KBMPEG-4 movie5KPMPEG-4 movie11 KBMPEG-4 movie26 KBMPEG-4 movie111 K:MPEG-4 movie102 KBMPEG-4 movie88 KB59 KBO9 KRMPEG-4 movieMDEG-A movie97 KB66 KBMPEG-4 movie44K:MPSG-A movid93 KBMPEG-4 movie78 KB50 KB59 KPMPEG-4 movieMPEG-4 movie27 KBMPEG-4 movie12 K:32 KBMPEG-4 movie17 KB19K8MPEG-4 movie• 0FavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-yWJo.zioPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dmaimage.jpg- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.jsonm licence bettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pa• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.63 GB availabld• Inu 14 May 1/.23.20Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45166
|
1621
|
18
|
2026-05-14T14:23:19.290478+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768599290_m1.jpg...
|
PhpStorm
|
faVsco.js – ActivityPlaybookTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:23:19* :QProject v© ReportController.php© AutomatedReportGenerated.php© TrackAutomatedReportGeneratedEvent.php:=custom.logPlaybackController.php> D CrmObjects© UserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php© SendReportJob.php• DecorateActivity› Dummy©DeleteCrmEntityTrait.php© DeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.phpT ActivityPlaybookTrait.php x› Helpers© AccountController.phpIntegrationAppTrait.phpE .env.stagingE.env© DetachActivityObject.phpv HubspotRematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.php18D AccountSyncStrate› D ActionsD ContactSyncStrate!17HandleHubspotRateLimit.phptrait ActivityPlaybookTraitAnalyzing….> DDTO18› O Fields› D JournalMetadata1920protected CrmHelperRepository ScrmHelperRepository;v OpportunitySyncSti> [ Concerns21public function getPlaybookFromActivity(Activity $activity): ?Playbook{...}© HubspotLastMor29© HubspotLastMor30© HubspotLastMor31© HubspotLastMor32/***/* Gets the playbook for the user© HubspotLastMor© HubspotSingleS:33protected function getPlaybook(User $user): ?Playbook{...}© HubspotSyncStr39© HubspotWebhocv D Pagination40protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory{...}© HubspotPaginati 44© PaginationConfig© PaginationState.45public function matchesCrmType(PlaybookCategory $category): bool> D ProspectSearchStre46› [ Redis.47v D ServiceTraits48€ OpportunitySync49$playbook = $category->getPlaybook():if ($playbook === null) {return false;© SyncCrmEntities50+ SyncFieldsTrait./51T WriteCrmTrait.pl52C Utils53C Webhook54SactivityField = $playbook->getActivityFieldO;if ($activityField === null) {return false;@ RatchSuneCollerto 55Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]DGo jiminny08A1A3X4 ^ V211m migrations oi212213214215216m teams wherem crm_layouts !M crm_layout_eiM crm_fields Wi217218219220m features;m team_feature:m opportunitie:221222m teams:223224I.id, CASE WHEN225226227228229230,id FROM social,on u.id = sa.:1..n<->1: on t._id = 1052 and231232233 /IMaccounts wheiactivities23445:21UTF-8C 4 spaces...
|
NULL
|
-8906165182920389014
|
NULL
|
visual_change
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:23:19* :QProject v© ReportController.php© AutomatedReportGenerated.php© TrackAutomatedReportGeneratedEvent.php:=custom.logPlaybackController.php> D CrmObjects© UserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php© SendReportJob.php• DecorateActivity› Dummy©DeleteCrmEntityTrait.php© DeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.phpT ActivityPlaybookTrait.php x› Helpers© AccountController.phpIntegrationAppTrait.phpE .env.stagingE.env© DetachActivityObject.phpv HubspotRematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.php18D AccountSyncStrate› D ActionsD ContactSyncStrate!17HandleHubspotRateLimit.phptrait ActivityPlaybookTraitAnalyzing….> DDTO18› O Fields› D JournalMetadata1920protected CrmHelperRepository ScrmHelperRepository;v OpportunitySyncSti> [ Concerns21public function getPlaybookFromActivity(Activity $activity): ?Playbook{...}© HubspotLastMor29© HubspotLastMor30© HubspotLastMor31© HubspotLastMor32/***/* Gets the playbook for the user© HubspotLastMor© HubspotSingleS:33protected function getPlaybook(User $user): ?Playbook{...}© HubspotSyncStr39© HubspotWebhocv D Pagination40protected function getPlaybookCategory(Playbook $playbook, string $categoryName): ?PlaybookCategory{...}© HubspotPaginati 44© PaginationConfig© PaginationState.45public function matchesCrmType(PlaybookCategory $category): bool> D ProspectSearchStre46› [ Redis.47v D ServiceTraits48€ OpportunitySync49$playbook = $category->getPlaybook():if ($playbook === null) {return false;© SyncCrmEntities50+ SyncFieldsTrait./51T WriteCrmTrait.pl52C Utils53C Webhook54SactivityField = $playbook->getActivityFieldO;if ($activityField === null) {return false;@ RatchSuneCollerto 55Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]DGo jiminny08A1A3X4 ^ V211m migrations oi212213214215216m teams wherem crm_layouts !M crm_layout_eiM crm_fields Wi217218219220m features;m team_feature:m opportunitie:221222m teams:223224I.id, CASE WHEN225226227228229230,id FROM social,on u.id = sa.:1..n<->1: on t._id = 1052 and231232233 /IMaccounts wheiactivities23445:21UTF-8C 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45165
|
1622
|
7
|
2026-05-14T14:23:16.741515+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768596741_m2.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Search
matchesCrmType (ActivityPlaybookTrait .../a Search
matchesCrmType (ActivityPlaybookTrait .../app/Services/Crm/Helpers), public method
matchesCrmType (WriteCrmTraitTest .../tests/Unit/Services/Crm/Hubspot/ServiceTraits), public method
Choose Declaration...
|
[{"role":"AXTextField","text [{"role":"AXTextField","text":"Search","depth":1,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"matchesCrmType (ActivityPlaybookTrait .../app/Services/Crm/Helpers), public method","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"matchesCrmType (WriteCrmTraitTest .../tests/Unit/Services/Crm/Hubspot/ServiceTraits), public method","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Choose Declaration","depth":1,"on_screen":true,"role_description":"text"}]...
|
7591294825150517262
|
981909621225921017
|
click
|
accessibility
|
NULL
|
Search
matchesCrmType (ActivityPlaybookTrait .../a Search
matchesCrmType (ActivityPlaybookTrait .../app/Services/Crm/Helpers), public method
matchesCrmType (WriteCrmTraitTest .../tests/Unit/Services/Crm/Hubspot/ServiceTraits), public method
Choose Declaration...
|
45162
|
NULL
|
NULL
|
NULL
|
|
45164
|
1621
|
17
|
2026-05-14T14:23:16.259006+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768596259_m1.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Search
matchesCrmType (ActivityPlaybookTrait .../a Search
matchesCrmType (ActivityPlaybookTrait .../app/Services/Crm/Helpers), public method
matchesCrmType (WriteCrmTraitTest .../tests/Unit/Services/Crm/Hubspot/ServiceTraits), public method
Choose Declaration...
|
[{"role":"AXTextField","text [{"role":"AXTextField","text":"Search","depth":1,"on_screen":false,"role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"matchesCrmType (ActivityPlaybookTrait .../app/Services/Crm/Helpers), public method","depth":4,"bounds":{"left":0.5069444,"top":0.69,"width":0.49166667,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"matchesCrmType (WriteCrmTraitTest .../tests/Unit/Services/Crm/Hubspot/ServiceTraits), public method","depth":4,"bounds":{"left":0.5069444,"top":0.71444446,"width":0.49166667,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Choose Declaration","depth":1,"bounds":{"left":0.5138889,"top":0.6533333,"width":0.47777778,"height":0.036666665},"on_screen":true,"role_description":"text"}]...
|
7591294825150517262
|
981909621225921017
|
visual_change
|
accessibility
|
NULL
|
Search
matchesCrmType (ActivityPlaybookTrait .../a Search
matchesCrmType (ActivityPlaybookTrait .../app/Services/Crm/Helpers), public method
matchesCrmType (WriteCrmTraitTest .../tests/Unit/Services/Crm/Hubspot/ServiceTraits), public method
Choose Declaration...
|
45163
|
NULL
|
NULL
|
NULL
|
|
45163
|
1621
|
16
|
2026-05-14T14:23:13.247292+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768593247_m1.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:23:12* :QProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php=custom.log> D CrmObjectsUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php• DecorateActivity› D Dummy• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.php x© AccountController.php› HelpersT IntegrationAppTrait.php.env.staging.envDetachActivityObject.phpRematchActivityOnCrmObjectDetach.phpv Hubspot© Client.php18D AccountSyncStrate› D ActionsD ContactSyncStrate!> DDTO› O Fields› D Journal© MatchActivityCrmData.phptrait WriteCrmTrait* @throws HubspotException* @throws BadRequest*/1 usageHubspotPaginationService.phpHandleHubspotRateLimit.php19525354Metadata55private function buildConferencePayload(Activity Sactivity): Activity56v OpportunitySyncSti> [ Concerns57$decorator = Sthis->getDecorateActivityO;© HubspotLastMor58© HubspotLastMor59© HubspotLastMor60© HubspotLastMor6162© HubspotLastMor63© HubspotSingleS:$engagement = l'active'= true,'ownerid' => Sthis->profile->getCrmProviderId(),'timestamp' => $decorator->formatStartTime(Sactivity),'type' => 'MEETING',64© HubspotSyncStr]:© HubspotWebhoc6566v D Pagination© HubspotPaginati6768© PaginationConfig© PaginationState.6970> D ProspectSearchStra> [ Redis71if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType))) {$engagement['activityType'] = $activity->getAct< 1/2 >T ActivityPlaybookTraitpublic function matchesCrmType(PlaybookCategory Scategory: boolv D ServiceTraits72Smetadata = ['meetingOutcome' => $decorator->convertMeeting0'internalMeetingNotes' => $decorator->generateD€ OpportunitySync73];© SyncCrmEntities74Parameters: \PlaybookCategory$category+ SyncFieldsTrait./75// Only if they are creating a fresh engagementshoT WriteCrmTrait.pl76if (! $activity->hasCrmProviderId()) {Source:.../app/Services/Crm/Helpers/ActivityPlaybookTrait.phpD Utils77if (Sactivity->hasActualStartTime() && $activitD Webhook78Smetadata('startTime'] = $decorator->format@ RatchSvneCnllertn'79Smetadata["ondTime!]l= Sdeconaton->formatEndTime (Sactivity):Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] XA8M6AY4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial.1 on u.id= sa.:1..n<->1: on t.L_id = 1052 andLUcauseaD-—211212213214215216217218— 219220221222223224225=226_227228229230231232- 233 V234IMaccounts wheiactivitiesW Windsurf Teams66:60UTF-8Co 4 spaces...
|
NULL
|
-525233212572782706
|
NULL
|
visual_change
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:23:12* :QProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php=custom.log> D CrmObjectsUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php• DecorateActivity› D Dummy• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.php x© AccountController.php› HelpersT IntegrationAppTrait.php.env.staging.envDetachActivityObject.phpRematchActivityOnCrmObjectDetach.phpv Hubspot© Client.php18D AccountSyncStrate› D ActionsD ContactSyncStrate!> DDTO› O Fields› D Journal© MatchActivityCrmData.phptrait WriteCrmTrait* @throws HubspotException* @throws BadRequest*/1 usageHubspotPaginationService.phpHandleHubspotRateLimit.php19525354Metadata55private function buildConferencePayload(Activity Sactivity): Activity56v OpportunitySyncSti> [ Concerns57$decorator = Sthis->getDecorateActivityO;© HubspotLastMor58© HubspotLastMor59© HubspotLastMor60© HubspotLastMor6162© HubspotLastMor63© HubspotSingleS:$engagement = l'active'= true,'ownerid' => Sthis->profile->getCrmProviderId(),'timestamp' => $decorator->formatStartTime(Sactivity),'type' => 'MEETING',64© HubspotSyncStr]:© HubspotWebhoc6566v D Pagination© HubspotPaginati6768© PaginationConfig© PaginationState.6970> D ProspectSearchStra> [ Redis71if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType))) {$engagement['activityType'] = $activity->getAct< 1/2 >T ActivityPlaybookTraitpublic function matchesCrmType(PlaybookCategory Scategory: boolv D ServiceTraits72Smetadata = ['meetingOutcome' => $decorator->convertMeeting0'internalMeetingNotes' => $decorator->generateD€ OpportunitySync73];© SyncCrmEntities74Parameters: \PlaybookCategory$category+ SyncFieldsTrait./75// Only if they are creating a fresh engagementshoT WriteCrmTrait.pl76if (! $activity->hasCrmProviderId()) {Source:.../app/Services/Crm/Helpers/ActivityPlaybookTrait.phpD Utils77if (Sactivity->hasActualStartTime() && $activitD Webhook78Smetadata('startTime'] = $decorator->format@ RatchSvneCnllertn'79Smetadata["ondTime!]l= Sdeconaton->formatEndTime (Sactivity):Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] XA8M6AY4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial.1 on u.id= sa.:1..n<->1: on t.L_id = 1052 andLUcauseaD-—211212213214215216217218— 219220221222223224225=226_227228229230231232- 233 V234IMaccounts wheiactivitiesW Windsurf Teams66:60UTF-8Co 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45162
|
1622
|
6
|
2026-05-14T14:23:10.561487+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768590561_m2.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterday at 13.34Yesterday at 13:34Yesterday at 13.33Yesterdav at 13:32resterday al i5.sYesterdav at 13:31Yesterday at 13:30Yesterday at 13.29Yesterday at 13:29resterday at 15.2oYesterday at 13:27Yesterday at 13:26Yesterday at 13:26Yesterday at 13:25Yesterday at 13.24Yesterdav at 13:24Yesterday at 13:23Yesterday at 13:21Yesterday at 13:21Yesterday at 13.20Yesterdav at 13:19Yesterday at 13:19Yesterday at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13.16Yecterdav at 12:16Yesterday at 13:15Yesterday at 13.10Yesterdav at 13:14Yesterday at 13:14Yesterday at 13:13Yecterdav at 12:12Yesterday at 13.11Yesterdav at 13:11Yesterday at 13:10Yesterday at 13:09Yesterday at 13:09Yesterday at 13:08Yesterday at 13.08Yecterdav at 12:07Yesterday at 13:07Yesterdav at 13:0617K:MPEG-4 movie29 KBMPEG-4 movie6 KB12 Kb9 KBIMPEG-4 movieMPEG-4 movie7 KB8 KBMPEG-4 movie37 K:10 KBMPEG-4 movie7 KBMPEG-4 movie9 KBMPEG-4 movie8 KB72 KBMPEG-4 movie14 K:13 KBMPEG-4 movie9 KB18 KB|MPEG-4 movie12 KBMPEG-4 movie10 KB16 KBMPEG-4 movie6KEMPEG-4 movie6 KB MPEG-4 movie12 KB23 K:MPEG-4 movie8 KBMPEG-4 movie6 KBMPEG-4 movie11 KEMPEG-4 movie11 KBMPEG-4 movie20 KB34 K:MPEG-4 movie10 KBMPEG-4 movie7 KB5KBMPEG-4 movie11 KPMPEG-4 movie26 KB MPEG-4 movie111 KBMPEG-4 movie102 K:MPEG-4 movie88 KBMPEG-4 movie59 KB98 KBMPEG-4 movie07 KPMDEG-A movie66 KBMPEG-4 movie44 KBMPEG-4 movie03 K:IMPEG-A movid78 KB MPEG-4 movie50 KB58 KB27 KPMPEG-4 movieMPEG-4 movie7 KB12 KBMPEG-4 movie22 K:17 KBMPEG-4 movie19 KB32 K8MPEG-4 movieFavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-ywJo.ziPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dmaimage.jpg- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.63 GB availabld• Inu 14 Mаy 1/.23.10Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
-5443580408892116924
|
NULL
|
click
|
ocr
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterday at 13.34Yesterday at 13:34Yesterday at 13.33Yesterdav at 13:32resterday al i5.sYesterdav at 13:31Yesterday at 13:30Yesterday at 13.29Yesterday at 13:29resterday at 15.2oYesterday at 13:27Yesterday at 13:26Yesterday at 13:26Yesterday at 13:25Yesterday at 13.24Yesterdav at 13:24Yesterday at 13:23Yesterday at 13:21Yesterday at 13:21Yesterday at 13.20Yesterdav at 13:19Yesterday at 13:19Yesterday at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13.16Yecterdav at 12:16Yesterday at 13:15Yesterday at 13.10Yesterdav at 13:14Yesterday at 13:14Yesterday at 13:13Yecterdav at 12:12Yesterday at 13.11Yesterdav at 13:11Yesterday at 13:10Yesterday at 13:09Yesterday at 13:09Yesterday at 13:08Yesterday at 13.08Yecterdav at 12:07Yesterday at 13:07Yesterdav at 13:0617K:MPEG-4 movie29 KBMPEG-4 movie6 KB12 Kb9 KBIMPEG-4 movieMPEG-4 movie7 KB8 KBMPEG-4 movie37 K:10 KBMPEG-4 movie7 KBMPEG-4 movie9 KBMPEG-4 movie8 KB72 KBMPEG-4 movie14 K:13 KBMPEG-4 movie9 KB18 KB|MPEG-4 movie12 KBMPEG-4 movie10 KB16 KBMPEG-4 movie6KEMPEG-4 movie6 KB MPEG-4 movie12 KB23 K:MPEG-4 movie8 KBMPEG-4 movie6 KBMPEG-4 movie11 KEMPEG-4 movie11 KBMPEG-4 movie20 KB34 K:MPEG-4 movie10 KBMPEG-4 movie7 KB5KBMPEG-4 movie11 KPMPEG-4 movie26 KB MPEG-4 movie111 KBMPEG-4 movie102 K:MPEG-4 movie88 KBMPEG-4 movie59 KB98 KBMPEG-4 movie07 KPMDEG-A movie66 KBMPEG-4 movie44 KBMPEG-4 movie03 K:IMPEG-A movid78 KB MPEG-4 movie50 KB58 KB27 KPMPEG-4 movieMPEG-4 movie7 KB12 KBMPEG-4 movie22 K:17 KBMPEG-4 movie19 KB32 K8MPEG-4 movieFavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-ywJo.ziPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dmaimage.jpg- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.63 GB availabld• Inu 14 Mаy 1/.23.10Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45161
|
1621
|
15
|
2026-05-14T14:23:10.574462+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768590574_m1.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
8043719072324535154
|
-8628527368849355612
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
PhpStormFileEditViewNavig Project: faVsco.js, menu
PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:23:10* :QProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php=custom.log> D CrmObjectsUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php• DecorateActivity› D Dummy• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.php x© AccountController.php› HelpersT IntegrationAppTrait.php.env.staging.envDetachActivityObject.phpRematchActivityOnCrmObjectDetach.phpv Hubspot© Client.php18D AccountSyncStrate› D ActionsD ContactSyncStrate!> DDTO› O Fields© MatchActivityCrmData.phptrait WriteCrmTrait* Othrows HubspotException* Othrows BadRequest*/1 usage© HubspotPaginationService.phpHandleHubspotRateLimit.php19525354A8M6AY› D Journal55private function buildConferencePayload(Activity Sactivity): ActivityMetadata56v OpportunitySyncSti57$decorator = $this->getDecorateActivity®:> [ Concerns58© HubspotLastMor59© HubspotLastMor60© HubspotLastMor61© HubspotLastMor62© HubspotLastMor63© HubspotSingleS:$engagement = ['active' => true,'ownerId' => $this->profile->getCrmProviderId(.'timestamp' => $decorator->formatStartTime(Sactivity),'type' => 'MEETING',64© HubspotSyncStr]:65© HubspotWebhoc66v D Pagination67if ($activity->hasActivityType() && $this-›matchesCrmType($activity->getActivityType())) {$engagement['activityType'] = $activity->getActivityType()->getName();D-—211212213214215216217218— 219220221Cascade & TI© HubspotPaginati68© PaginationConfig69224© PaginationState.22570> D ProspectSearchStra71> [ Redis72v D ServiceTraits$metadata = ['meetingOutcome' => $decorator->convertMeetingOutcome(Sactivity),'internalMeetingNotes' => $decorator-›generateDescription(Sactivity),=226_22773€ OpportunitySync1:22822974© SyncCrmEntities75230+ SyncFieldsTrait./// Only if they are creating a fresh engagement should we update the times, otherwise it will cause at76231if (! $activity->hasCrmProviderId)) {T WriteCrmTrait.pl77if (Sactivity->hasActualStartTime() && $activity->hasActualEndTime)232D Utils78— 233 VSmetadata['startTime'] = $decorator->formatStartTime($activity);D Webhook79@ RatchSvneCnllertn'Smetadata['endTime'] = $decorator->formatEndTime(Sactivity);234Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:Command 8811.id,CASEWHENidFROMsocial,I on u.id= sa.:1..n<->1: on t.L_id = 1052 andIMaccounts wheiactivitiesW Windsurf Teams66:39 (15 chars)UTF-8Co 4 spaces...
|
45158
|
NULL
|
NULL
|
NULL
|
|
45160
|
1622
|
5
|
2026-05-14T14:23:08.543772+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768588543_m2.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.2962101,"top":1.0,"width":0.03856383,"height":-0.019952059},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.33477393,"top":1.0,"width":0.122340426,"height":-0.019952059},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.5731383,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.5884308,"top":1.0,"width":0.076130316,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.66456115,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.67586434,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.6871675,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.7150931,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.72639626,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.73769945,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"6","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","depth":4,"bounds":{"left":0.39162233,"top":0.41340783,"width":0.31615692,"height":0.5865922},"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"4","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","depth":4,"on_screen":true,"value":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.28224733,"top":1.0,"width":0.024268618,"height":-0.04788506},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
3382584868951134281
|
6551498163460912845
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
45159
|
NULL
|
NULL
|
NULL
|
|
45159
|
1622
|
4
|
2026-05-14T14:23:05.452772+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768585452_m2.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.2962101,"top":1.0,"width":0.03856383,"height":-0.019952059},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.33477393,"top":1.0,"width":0.122340426,"height":-0.019952059},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.5731383,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.5884308,"top":1.0,"width":0.076130316,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.66456115,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-7759925082980464890
|
-7195274138718106135
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterday at 13.34Yesterday at 13:34Yesterday at 13.33Yesterdav at 13:32resterday al i5.sYesterdav at 13:31Yesterday at 13:30Yesterday at 13.29Yesterday at 13:29resterday at 15.2oYesterday at 13:27Yesterday at 13:26Yesterday at 13:26Yesterday at 13:25Yesterday at 13.24Yesterdav at 13:24Yesterday at 13:23Yesterday at 13:21Yesterday at 13:21Yesterday at 13.20Yesterdav at 13:19Yesterday at 13:19Yesterday at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13.16Yecterdav at 12:16Yesterday at 13:15resterday at 13-10Yesterdav at 13:14Yesterday at 13:14Yesterday at 13:13Yecterdav at 12:12Yesterday at 13.11Yesterdav at 13:11Yesterday at 13:10Yesterday at 13:09Yesterday at 13:09Yesterday at 13:08Yesterday at 13.08Yecterdav at 12:07Yesterday at 13:07Yesterdav at 13:0617K:MPEG-4 movie29 KBMPEG-4 movie6 KB12 Kb9 KBIMPEG-4 movieMPEG-4 movie7 KB8 KBMPEG-4 movie37 K:10 KBMPEG-4 movie7 KBMPEG-4 movie9 KBMPEG-4 movie8 KB72 KBMPEG-4 movie14 K:13 KBMPEG-4 movie9 KB18 KB|12 KBIMPEG-4 movieMPEG-4 movie10 KB16 KBMPEG-4 movie6KEMPEG-4 movie6 KB MPEG-4 movie12 KB23 K:MPEG-4 movie8 KBMPEG-4 movie6 KBMPEG-4 movie11 KEMPEG-4 movie11 KBMPEG-4 movie20 KB34 K:MPEG-4 movie10 KBMPEG-4 movie7 KB5KBMPEG-4 movie11 KPMPEG-4 movie26 KB MPEG-4 movie111 KBMPEG-4 movie102 K:MPEG-4 movie88 KBMPEG-4 movie59 KB98 KBMPEG-4 movie07 KPMDEG-A movie66 KBMPEG-4 movie44 KBMPEG-4 movie03 K:IMPEG-A movid78 KB MPEG-4 movie50 KB58 KB27 KPMPEG-4 movieMPEG-4 movie7 KB12 KBMPEG-4 movie22 K:17 KBMPEG-4 movie19 KB32 K8MPEG-4 movieFavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-ywJo.ziPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dmaimage.jpg- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.63 GB availabld• Inu 14 May 1/-23.02Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45158
|
1621
|
14
|
2026-05-14T14:23:07.298201+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768587298_m1.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.054166667,"top":0.027777778,"width":0.08055556,"height":0.035555556},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.13472222,"top":0.027777778,"width":0.25555557,"height":0.035555556},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.6326389,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.6645833,"top":0.027777778,"width":0.15902779,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.82361114,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.8472222,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.87083334,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.9291667,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9527778,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9763889,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"bounds":{"left":0.78055555,"top":0.24333334,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"6","depth":4,"bounds":{"left":0.80138886,"top":0.24333334,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.8215278,"top":0.24111111,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.8368056,"top":0.24111111,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Services\\Crm\\Hubspot\\ServiceTraits;\n\nuse Carbon\\Carbon;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Repositories\\Crm\\FieldDataRepository;\nuse Jiminny\\Services\\Crm\\Hubspot\\DecorateActivity;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationCategoryV4;\nuse Jiminny\\Services\\Crm\\Hubspot\\Utils\\AssociationTypeIdV4;\nuse SevenShores\\Hubspot\\Exceptions\\BadRequest;\nuse SevenShores\\Hubspot\\Http\\Response;\nuse SevenShores\\Hubspot\\Exceptions\\HubspotException;\nuse Sentry;\n\ntrait WriteCrmTrait\n{\n private const string ACTION_CREATE = 'create';\n private const string ACTION_UPDATE = 'update';\n private const string ACTION_DELETE = 'delete';\n\n /**\n * @inheritdoc\n */\n public function saveActivity(Activity $activity): Activity\n {\n switch ($activity->getCrmType()) {\n case Activity::TYPE_CONFERENCE:\n $activity = $this->buildConferencePayload($activity);\n\n break;\n case Activity::TYPE_SOFTPHONE:\n case Activity::TYPE_SOFTPHONE_INBOUND:\n $activity = $this->buildSoftphonePayload($activity);\n\n break;\n\n case Activity::TYPE_SMS_INBOUND:\n case Activity::TYPE_SMS_OUTBOUND:\n $activity = $this->buildTextMessagePayload($activity);\n\n break;\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildConferencePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatStartTime($activity),\n 'type' => 'MEETING',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'meetingOutcome' => $decorator->convertMeetingOutcome($activity),\n 'internalMeetingNotes' => $decorator->generateDescription($activity),\n ];\n\n // Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.\n if (! $activity->hasCrmProviderId()) {\n if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {\n $metadata['startTime'] = $decorator->formatStartTime($activity);\n $metadata['endTime'] = $decorator->formatEndTime($activity);\n }\n $metadata['title'] = $decorator->generateTitle($activity);\n }\n\n // For now, this is just a \"meetingOutcome\" field for some customers.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function fetchCustomFieldData(Activity $activity, string $objectType): array\n {\n $payload = [];\n\n $fieldDataRepository = app(FieldDataRepository::class);\n $fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);\n\n foreach ($fieldData as $data) {\n // Add the field and value to the payload.\n $payload += [\n $data->getField()->getCrmProviderId() => $data->getValue(),\n ];\n }\n\n return $payload;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity\n {\n if (! $activity->hasCrmProviderId()) {\n $this->createActivity($activity, $engagement, $metadata);\n\n return $activity;\n }\n\n try {\n $oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());\n } catch (HubspotException $e) {\n $this->logger->warning('[HubSpot] Engagement not found', [\n 'activity_id' => $activity->getUuid(),\n 'crm_provider_id' => $activity->getCrmProviderId(),\n 'exception' => $e->getMessage(),\n ]);\n\n // potentially here we can log new activity if it is not found\n\n return $activity;\n }\n\n $type = $oldEngagement['engagement']['type'] ?? null;\n $bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';\n\n $decorator = $this->getDecorateActivity();\n\n if ($type !== 'TASK') {\n $oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldDescription\n );\n\n $oldAssociations = $oldEngagement['associations'] ?? [];\n $this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);\n } else {\n $oldTaskBody = $oldEngagement['metadata']['body'] ?? '';\n $metadata[$bodyAttribute] = $decorator->mergeDescriptions(\n $metadata[$bodyAttribute],\n $oldTaskBody\n );\n $this->updateTask($activity, $engagement, $metadata);\n }\n\n return $activity;\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateNonTaskActivity(\n Activity $activity,\n array $engagement,\n array $metadata,\n array $oldAssociations\n ): void {\n if ($activity->isTypeConference()) {\n $this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);\n } else {\n $this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);\n }\n\n $this->updateActivityAssociations($activity, $oldAssociations);\n\n $this->logCrmEngagementManipulation(\n self::ACTION_UPDATE,\n ['crmId' => $activity->getCrmProviderId()],\n $metadata,\n );\n }\n\n private function updateActivityAssociations(Activity $activity, array $oldAssociations): void\n {\n $currentAssociations = $this->getActivityAssociations($activity);\n $associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);\n\n // No changes - exit\n if (empty($associationChanges)) {\n return;\n }\n\n $this->logger->info('[HubSpot] Updating associations', [\n 'team' => $this->team->getUuid(),\n 'activity' => $activity->getUuid(),\n 'associationChanges' => $associationChanges,\n ]);\n\n $this->updateAssociations($activity, $associationChanges);\n }\n\n private function getAssociationDifferences(\n Activity $activity,\n array $oldAssociations,\n array $currentAssociations\n ): array {\n $objects = ['contactIds', 'companyIds', 'dealIds'];\n $changes = [];\n\n foreach ($objects as $object) {\n $oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);\n $currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);\n\n $added = array_diff($currentIds, $oldIds);\n $removed = array_diff($oldIds, $currentIds);\n\n $type = match ($object) {\n 'contactIds' => 'contact',\n 'companyIds' => 'company',\n 'dealIds' => 'deal',\n };\n\n $shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);\n\n if (! empty($removed) && ! $shouldIncludeRemoved) {\n $this->logger->info('[HubSpot] Skipping association removal', [\n 'team' => $this->team->getUuid(),\n 'type' => $type,\n 'oldIds' => $oldIds,\n 'currentIds' => $currentIds,\n 'skippedRemovals' => array_values($removed),\n ]);\n }\n\n if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {\n $changes[$type] = [\n 'added' => array_values($added),\n 'removed' => array_values($removed),\n ];\n }\n }\n\n return $changes;\n }\n\n /**\n * Determines whether removed associations should be synced to HubSpot.\n *\n * For contacts and companies, we always sync removals (original behavior).\n * For deals, we only sync removals when:\n * - There are new deals being added (replacement scenario), OR\n * - The activity has an account associated (indicating intentional association management)\n *\n * This prevents accidentally removing deal associations that exist in HubSpot\n * but not in Jiminny's database (e.g., deals manually added by users in HubSpot).\n */\n private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool\n {\n // Contacts and companies: always sync removals\n if ($type !== 'deal') {\n return true;\n }\n\n // Deals: sync removals if we're adding new deals (replacement)\n if (! empty($added)) {\n return true;\n }\n\n // Deals: sync removals only if activity has an account (intentional management)\n return $activity->hasAccount();\n }\n\n private function normalizeIds(array $ids): array\n {\n $stringIds = array_map('strval', $ids);\n $uniqueIds = array_unique($stringIds);\n sort($uniqueIds);\n\n return $uniqueIds;\n }\n\n private function updateAssociations(Activity $activity, array $associationChanges): void\n {\n $objectType = $activity->isTypeConference() ? 'meeting' : 'call';\n\n foreach ($associationChanges as $type => $changes) {\n if (! empty($changes['added'])) {\n $associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);\n $payload = $this->payloadBuilder->buildAddAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['added'],\n $associationType\n );\n $this->getClient()->addAssociations($objectType, $type, $payload);\n }\n\n if (! empty($changes['removed'])) {\n $payload = $this->payloadBuilder->buildRemoveAssociationPayload(\n $activity->getCrmProviderId(),\n $changes['removed']\n );\n $this->getClient()->removeAssociations($objectType, $type, $payload);\n }\n }\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response\n {\n // If already set by us/client, do not override it\n if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {\n $this->logger->info('[HubSpot] Meeting activity type already set', [\n 'meetingId' => $meetingId,\n 'activityType' => $engagement['activityType'],\n ]);\n\n unset($engagement['activityType']);\n }\n\n $payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);\n\n return $this->getClient()->updateMeeting($meetingId, $payload);\n }\n\n private function hasEngagementActivityType(string $engagementId): bool\n {\n try {\n $engagementData = $this->getClient()->getEngagementData($engagementId);\n if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {\n return true;\n }\n\n return false;\n } catch (\\Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [\n 'engagementId' => $engagementId,\n 'exception' => $exception->getMessage(),\n ]);\n }\n\n return true;\n }\n\n private function updateTask(Activity $activity, array $engagement, array $metadata): void\n {\n $this->getClient()->deleteEngagement($activity->getCrmProviderId());\n\n $this->logCrmEngagementManipulation(\n self::ACTION_DELETE,\n ['crmId' => $activity->getCrmProviderId()],\n );\n\n $this->createActivity($activity, $engagement, $metadata);\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createActivity(Activity $activity, array $engagement, array $metadata): void\n {\n $associations = $this->getActivityAssociations($activity);\n $associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);\n\n if ($activity->isTypeConference()) {\n try {\n $hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);\n $activityId = $hsEngagement->data->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n } else {\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n $activityId = $hsEngagement->data->engagement->id;\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n $activity->crm_provider_id = $activityId;\n $activity->save();\n } catch (BadRequest $exception) {\n Sentry::captureException($exception);\n\n $this->logger->warning('[HubSpot] Error while creating engagements', [\n 'activity' => $activity->getUuid(),\n 'message' => $exception->getMessage(),\n 'engagement' => $engagement,\n 'associations' => $associations,\n 'metadata' => $metadata,\n ]);\n }\n }\n }\n\n private function convertActivityMeetingAssociationsV4(Activity $activity): array\n {\n $associations = [];\n\n $contactIds = $this->getParticipantsIds($activity);\n\n foreach ($contactIds as $contactId) {\n $associations[] = $this->buildAssociation(\n (int) $contactId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]\n );\n }\n\n if ($activity->hasAccount()) {\n $crmProviderId = $activity->getAccount()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]\n );\n }\n }\n\n if ($activity->hasOpportunity()) {\n $crmProviderId = $activity->getOpportunity()?->getCrmProviderId();\n if ($crmProviderId) {\n $associations[] = $this->buildAssociation(\n (int) $crmProviderId,\n [AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]\n );\n }\n }\n\n return $associations;\n }\n\n private function buildAssociation(int $id, array $categoryToTypeIds): array\n {\n $types = [];\n\n foreach ($categoryToTypeIds as $category => $typeId) {\n $types[] = $this->buildAssociationType($category, $typeId);\n }\n\n return [\n 'to' => ['id' => (string) $id],\n 'types' => $types,\n ];\n }\n\n private function buildAssociationType(string $category, int $typeId): array\n {\n return [\n 'associationCategory' => $category,\n 'associationTypeId' => $typeId,\n ];\n }\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function createMeetingV3(array $engagement, array $associations, array $metadata): Response\n {\n $payload = $this->payloadBuilder->getV3MeetingPayload(\n engagement: $engagement,\n metadata: $metadata,\n associations: $associations\n );\n\n return $this->getClient()->createMeeting($payload);\n }\n\n /**\n * @throws BadRequest\n * @throws HubspotException\n */\n private function buildSoftphonePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'CALL',\n ];\n\n if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {\n $engagement['activityType'] = $activity->getActivityType()->getName();\n }\n\n $metadata = [\n 'toNumber' => $decorator->formatCallToParticipant($activity),\n 'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),\n 'status' => $decorator->convertCallStatus($activity),\n 'durationMilliseconds' => (int) $activity->getDuration() * 1000,\n 'body' => $decorator->generateDescription($activity),\n ];\n\n // For now, this is just a \"disposition\" field to store Call Outcome.\n $metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n\n /**\n * @throws HubspotException\n * @throws BadRequest\n */\n private function buildTextMessagePayload(Activity $activity): Activity\n {\n $decorator = $this->getDecorateActivity();\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $decorator->formatCreatedAt($activity),\n 'type' => 'NOTE',\n ];\n\n $metadata = [\n 'body' => $decorator->generateDescription($activity),\n ];\n\n return $this->upsertActivity($activity, $engagement, $metadata);\n }\n\n private function getActivityAssociations(Activity $activity): array\n {\n return [\n 'contactIds' => $this->getParticipantsIds($activity),\n 'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],\n 'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],\n 'ownerIds' => [],\n ];\n }\n\n /**\n * Get DecorateActivity instance. Can be overridden in tests for mocking.\n */\n protected function getDecorateActivity(): DecorateActivity\n {\n return new DecorateActivity();\n }\n\n public function saveFollowupActivity(Activity $activity, array $fields): ?string\n {\n if (empty($fields['subject'])) {\n return null;\n }\n\n $associations = $this->getActivityAssociations($activity);\n\n if (empty($fields['timestamp']) === false) {\n $formatTimestamp = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['timestamp']);\n $timestamp = $formatTimestamp->getTimestamp();\n } else {\n $timestamp = strtotime('+1 day');\n }\n\n $reminder = null;\n if (empty($fields['reminder']) === false) {\n $formatReminder = Carbon::createFromFormat('Y-m-d\\TH:i:s\\Z', $fields['reminder']);\n $reminder = $formatReminder->getTimestamp() * 1000;\n }\n\n $engagement = [\n 'active' => true,\n 'ownerId' => $this->profile->getCrmProviderId(),\n 'timestamp' => $timestamp * 1000,\n 'type' => 'TASK',\n ];\n\n $metadata = [\n 'subject' => $fields['subject'],\n 'body' => '',\n 'status' => 'NOT_STARTED',\n 'taskType' => 'CALL',\n 'reminders' => $reminder ? [$reminder] : [],\n ];\n\n try {\n $hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);\n } catch (BadRequest $e) {\n $this->logger->info('[HubSpot] Failed to create followup task', [\n 'activity' => $activity->getUuid(),\n 'engagement' => $engagement,\n 'metadata' => $metadata,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);\n\n // We don't actually create a corresponding activity object on our side yet.\n return (string) $hsEngagement->data->engagement->id;\n }\n\n private function logCrmEngagementManipulation(\n string $action,\n array $engagementData,\n array $data = [],\n array $associations = [],\n ): void {\n $payload = ['team' => $this->team->getUuid()];\n\n if ($action === self::ACTION_CREATE) {\n $payload['engagementData'] = $engagementData;\n $payload['data'] = $data;\n $payload['associations'] = $associations;\n }\n\n if ($action === self::ACTION_UPDATE) {\n $payload['engagementId'] = $engagementData['crmId'];\n $payload['data'] = $data;\n }\n\n if ($action === self::ACTION_DELETE) {\n $payload['engagementId'] = $engagementData['crmId'];\n }\n\n $this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.85486114,"top":0.31,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.87291664,"top":0.31,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.9138889,"top":0.31,"width":0.059027776,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"bounds":{"left":0.8645833,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.8854167,"top":0.34444445,"width":0.015277778,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.9048611,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"4","depth":4,"bounds":{"left":0.92569447,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.9458333,"top":0.3422222,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.9611111,"top":0.3422222,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","depth":4,"on_screen":true,"value":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.025,"top":0.06666667,"width":0.050694443,"height":0.034444444},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
3382584868951134281
|
6551498163460912845
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
8
6
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Services\Crm\Hubspot\ServiceTraits;
use Carbon\Carbon;
use Jiminny\Models\Activity;
use Jiminny\Models\Crm\Field;
use Jiminny\Repositories\Crm\FieldDataRepository;
use Jiminny\Services\Crm\Hubspot\DecorateActivity;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationCategoryV4;
use Jiminny\Services\Crm\Hubspot\Utils\AssociationTypeIdV4;
use SevenShores\Hubspot\Exceptions\BadRequest;
use SevenShores\Hubspot\Http\Response;
use SevenShores\Hubspot\Exceptions\HubspotException;
use Sentry;
trait WriteCrmTrait
{
private const string ACTION_CREATE = 'create';
private const string ACTION_UPDATE = 'update';
private const string ACTION_DELETE = 'delete';
/**
* @inheritdoc
*/
public function saveActivity(Activity $activity): Activity
{
switch ($activity->getCrmType()) {
case Activity::TYPE_CONFERENCE:
$activity = $this->buildConferencePayload($activity);
break;
case Activity::TYPE_SOFTPHONE:
case Activity::TYPE_SOFTPHONE_INBOUND:
$activity = $this->buildSoftphonePayload($activity);
break;
case Activity::TYPE_SMS_INBOUND:
case Activity::TYPE_SMS_OUTBOUND:
$activity = $this->buildTextMessagePayload($activity);
break;
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildConferencePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatStartTime($activity),
'type' => 'MEETING',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'meetingOutcome' => $decorator->convertMeetingOutcome($activity),
'internalMeetingNotes' => $decorator->generateDescription($activity),
];
// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a cal sync.
if (! $activity->hasCrmProviderId()) {
if ($activity->hasActualStartTime() && $activity->hasActualEndTime()) {
$metadata['startTime'] = $decorator->formatStartTime($activity);
$metadata['endTime'] = $decorator->formatEndTime($activity);
}
$metadata['title'] = $decorator->generateTitle($activity);
}
// For now, this is just a "meetingOutcome" field for some customers.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function fetchCustomFieldData(Activity $activity, string $objectType): array
{
$payload = [];
$fieldDataRepository = app(FieldDataRepository::class);
$fieldData = $fieldDataRepository->getActivityFieldData($activity, $objectType);
foreach ($fieldData as $data) {
// Add the field and value to the payload.
$payload += [
$data->getField()->getCrmProviderId() => $data->getValue(),
];
}
return $payload;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function upsertActivity(Activity $activity, array $engagement, array $metadata): Activity
{
if (! $activity->hasCrmProviderId()) {
$this->createActivity($activity, $engagement, $metadata);
return $activity;
}
try {
$oldEngagement = $this->getClient()->getEngagementData($activity->getCrmProviderId());
} catch (HubspotException $e) {
$this->logger->warning('[HubSpot] Engagement not found', [
'activity_id' => $activity->getUuid(),
'crm_provider_id' => $activity->getCrmProviderId(),
'exception' => $e->getMessage(),
]);
// potentially here we can log new activity if it is not found
return $activity;
}
$type = $oldEngagement['engagement']['type'] ?? null;
$bodyAttribute = $activity->isTypeConference() ? 'internalMeetingNotes' : 'body';
$decorator = $this->getDecorateActivity();
if ($type !== 'TASK') {
$oldDescription = $oldEngagement['metadata'][$bodyAttribute] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldDescription
);
$oldAssociations = $oldEngagement['associations'] ?? [];
$this->updateNonTaskActivity($activity, $engagement, $metadata, $oldAssociations);
} else {
$oldTaskBody = $oldEngagement['metadata']['body'] ?? '';
$metadata[$bodyAttribute] = $decorator->mergeDescriptions(
$metadata[$bodyAttribute],
$oldTaskBody
);
$this->updateTask($activity, $engagement, $metadata);
}
return $activity;
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateNonTaskActivity(
Activity $activity,
array $engagement,
array $metadata,
array $oldAssociations
): void {
if ($activity->isTypeConference()) {
$this->updateMeetingV3($activity->getCrmProviderId(), $engagement, $metadata);
} else {
$this->getClient()->updateEngagement($activity->getCrmProviderId(), $engagement, $metadata);
}
$this->updateActivityAssociations($activity, $oldAssociations);
$this->logCrmEngagementManipulation(
self::ACTION_UPDATE,
['crmId' => $activity->getCrmProviderId()],
$metadata,
);
}
private function updateActivityAssociations(Activity $activity, array $oldAssociations): void
{
$currentAssociations = $this->getActivityAssociations($activity);
$associationChanges = $this->getAssociationDifferences($activity, $oldAssociations, $currentAssociations);
// No changes - exit
if (empty($associationChanges)) {
return;
}
$this->logger->info('[HubSpot] Updating associations', [
'team' => $this->team->getUuid(),
'activity' => $activity->getUuid(),
'associationChanges' => $associationChanges,
]);
$this->updateAssociations($activity, $associationChanges);
}
private function getAssociationDifferences(
Activity $activity,
array $oldAssociations,
array $currentAssociations
): array {
$objects = ['contactIds', 'companyIds', 'dealIds'];
$changes = [];
foreach ($objects as $object) {
$oldIds = $this->normalizeIds($oldAssociations[$object] ?? []);
$currentIds = $this->normalizeIds($currentAssociations[$object] ?? []);
$added = array_diff($currentIds, $oldIds);
$removed = array_diff($oldIds, $currentIds);
$type = match ($object) {
'contactIds' => 'contact',
'companyIds' => 'company',
'dealIds' => 'deal',
};
$shouldIncludeRemoved = $this->shouldIncludeRemovedAssociations($type, $added, $activity);
if (! empty($removed) && ! $shouldIncludeRemoved) {
$this->logger->info('[HubSpot] Skipping association removal', [
'team' => $this->team->getUuid(),
'type' => $type,
'oldIds' => $oldIds,
'currentIds' => $currentIds,
'skippedRemovals' => array_values($removed),
]);
}
if (! empty($added) || (! empty($removed) && $shouldIncludeRemoved)) {
$changes[$type] = [
'added' => array_values($added),
'removed' => array_values($removed),
];
}
}
return $changes;
}
/**
* Determines whether removed associations should be synced to HubSpot.
*
* For contacts and companies, we always sync removals (original behavior).
* For deals, we only sync removals when:
* - There are new deals being added (replacement scenario), OR
* - The activity has an account associated (indicating intentional association management)
*
* This prevents accidentally removing deal associations that exist in HubSpot
* but not in Jiminny's database (e.g., deals manually added by users in HubSpot).
*/
private function shouldIncludeRemovedAssociations(string $type, array $added, Activity $activity): bool
{
// Contacts and companies: always sync removals
if ($type !== 'deal') {
return true;
}
// Deals: sync removals if we're adding new deals (replacement)
if (! empty($added)) {
return true;
}
// Deals: sync removals only if activity has an account (intentional management)
return $activity->hasAccount();
}
private function normalizeIds(array $ids): array
{
$stringIds = array_map('strval', $ids);
$uniqueIds = array_unique($stringIds);
sort($uniqueIds);
return $uniqueIds;
}
private function updateAssociations(Activity $activity, array $associationChanges): void
{
$objectType = $activity->isTypeConference() ? 'meeting' : 'call';
foreach ($associationChanges as $type => $changes) {
if (! empty($changes['added'])) {
$associationType = (new AssociationTypeIdV4())->getAssociationType($objectType, $type);
$payload = $this->payloadBuilder->buildAddAssociationPayload(
$activity->getCrmProviderId(),
$changes['added'],
$associationType
);
$this->getClient()->addAssociations($objectType, $type, $payload);
}
if (! empty($changes['removed'])) {
$payload = $this->payloadBuilder->buildRemoveAssociationPayload(
$activity->getCrmProviderId(),
$changes['removed']
);
$this->getClient()->removeAssociations($objectType, $type, $payload);
}
}
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function updateMeetingV3(string $meetingId, array $engagement, array $metadata): Response
{
// If already set by us/client, do not override it
if (isset($engagement['activityType']) && $this->hasEngagementActivityType($meetingId)) {
$this->logger->info('[HubSpot] Meeting activity type already set', [
'meetingId' => $meetingId,
'activityType' => $engagement['activityType'],
]);
unset($engagement['activityType']);
}
$payload = $this->payloadBuilder->getV3MeetingPayload($engagement, $metadata);
return $this->getClient()->updateMeeting($meetingId, $payload);
}
private function hasEngagementActivityType(string $engagementId): bool
{
try {
$engagementData = $this->getClient()->getEngagementData($engagementId);
if (isset($engagementData['engagement']['activityType']) && trim($engagementData['engagement']['activityType']) != '') {
return true;
}
return false;
} catch (\Exception $exception) {
Sentry::captureException($exception);
$this->logger->info('[HubSpot] Exception checking engagement activity type, defaulting to preserve existing', [
'engagementId' => $engagementId,
'exception' => $exception->getMessage(),
]);
}
return true;
}
private function updateTask(Activity $activity, array $engagement, array $metadata): void
{
$this->getClient()->deleteEngagement($activity->getCrmProviderId());
$this->logCrmEngagementManipulation(
self::ACTION_DELETE,
['crmId' => $activity->getCrmProviderId()],
);
$this->createActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createActivity(Activity $activity, array $engagement, array $metadata): void
{
$associations = $this->getActivityAssociations($activity);
$associationsV4 = $this->convertActivityMeetingAssociationsV4($activity);
if ($activity->isTypeConference()) {
try {
$hsEngagement = $this->createMeetingV3($engagement, $associationsV4, $metadata);
$activityId = $hsEngagement->data->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associationsV4);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
} else {
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
$activityId = $hsEngagement->data->engagement->id;
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
$activity->crm_provider_id = $activityId;
$activity->save();
} catch (BadRequest $exception) {
Sentry::captureException($exception);
$this->logger->warning('[HubSpot] Error while creating engagements', [
'activity' => $activity->getUuid(),
'message' => $exception->getMessage(),
'engagement' => $engagement,
'associations' => $associations,
'metadata' => $metadata,
]);
}
}
}
private function convertActivityMeetingAssociationsV4(Activity $activity): array
{
$associations = [];
$contactIds = $this->getParticipantsIds($activity);
foreach ($contactIds as $contactId) {
$associations[] = $this->buildAssociation(
(int) $contactId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_CONTACT]
);
}
if ($activity->hasAccount()) {
$crmProviderId = $activity->getAccount()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_COMPANY]
);
}
}
if ($activity->hasOpportunity()) {
$crmProviderId = $activity->getOpportunity()?->getCrmProviderId();
if ($crmProviderId) {
$associations[] = $this->buildAssociation(
(int) $crmProviderId,
[AssociationCategoryV4::HUBSPOT_DEFINED => AssociationTypeIdV4::MEETING_TO_DEAL]
);
}
}
return $associations;
}
private function buildAssociation(int $id, array $categoryToTypeIds): array
{
$types = [];
foreach ($categoryToTypeIds as $category => $typeId) {
$types[] = $this->buildAssociationType($category, $typeId);
}
return [
'to' => ['id' => (string) $id],
'types' => $types,
];
}
private function buildAssociationType(string $category, int $typeId): array
{
return [
'associationCategory' => $category,
'associationTypeId' => $typeId,
];
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function createMeetingV3(array $engagement, array $associations, array $metadata): Response
{
$payload = $this->payloadBuilder->getV3MeetingPayload(
engagement: $engagement,
metadata: $metadata,
associations: $associations
);
return $this->getClient()->createMeeting($payload);
}
/**
* @throws BadRequest
* @throws HubspotException
*/
private function buildSoftphonePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'CALL',
];
if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType())) {
$engagement['activityType'] = $activity->getActivityType()->getName();
}
$metadata = [
'toNumber' => $decorator->formatCallToParticipant($activity),
'fromNumber' => $activity->getFromParticipant()?->getPhoneNumber(),
'status' => $decorator->convertCallStatus($activity),
'durationMilliseconds' => (int) $activity->getDuration() * 1000,
'body' => $decorator->generateDescription($activity),
];
// For now, this is just a "disposition" field to store Call Outcome.
$metadata = array_merge($metadata, $this->fetchCustomFieldData($activity, Field::OBJECT_TASK));
return $this->upsertActivity($activity, $engagement, $metadata);
}
/**
* @throws HubspotException
* @throws BadRequest
*/
private function buildTextMessagePayload(Activity $activity): Activity
{
$decorator = $this->getDecorateActivity();
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $decorator->formatCreatedAt($activity),
'type' => 'NOTE',
];
$metadata = [
'body' => $decorator->generateDescription($activity),
];
return $this->upsertActivity($activity, $engagement, $metadata);
}
private function getActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->getAccount()->getCrmProviderId()] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->getOpportunity()->getCrmProviderId()] : [],
'ownerIds' => [],
];
}
/**
* Get DecorateActivity instance. Can be overridden in tests for mocking.
*/
protected function getDecorateActivity(): DecorateActivity
{
return new DecorateActivity();
}
public function saveFollowupActivity(Activity $activity, array $fields): ?string
{
if (empty($fields['subject'])) {
return null;
}
$associations = $this->getActivityAssociations($activity);
if (empty($fields['timestamp']) === false) {
$formatTimestamp = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['timestamp']);
$timestamp = $formatTimestamp->getTimestamp();
} else {
$timestamp = strtotime('+1 day');
}
$reminder = null;
if (empty($fields['reminder']) === false) {
$formatReminder = Carbon::createFromFormat('Y-m-d\TH:i:s\Z', $fields['reminder']);
$reminder = $formatReminder->getTimestamp() * 1000;
}
$engagement = [
'active' => true,
'ownerId' => $this->profile->getCrmProviderId(),
'timestamp' => $timestamp * 1000,
'type' => 'TASK',
];
$metadata = [
'subject' => $fields['subject'],
'body' => '',
'status' => 'NOT_STARTED',
'taskType' => 'CALL',
'reminders' => $reminder ? [$reminder] : [],
];
try {
$hsEngagement = $this->getClient()->createEngagement($engagement, $associations, $metadata);
} catch (BadRequest $e) {
$this->logger->info('[HubSpot] Failed to create followup task', [
'activity' => $activity->getUuid(),
'engagement' => $engagement,
'metadata' => $metadata,
'error' => $e->getMessage(),
]);
return null;
}
$this->logCrmEngagementManipulation(self::ACTION_CREATE, $engagement, $metadata, $associations);
// We don't actually create a corresponding activity object on our side yet.
return (string) $hsEngagement->data->engagement->id;
}
private function logCrmEngagementManipulation(
string $action,
array $engagementData,
array $data = [],
array $associations = [],
): void {
$payload = ['team' => $this->team->getUuid()];
if ($action === self::ACTION_CREATE) {
$payload['engagementData'] = $engagementData;
$payload['data'] = $data;
$payload['associations'] = $associations;
}
if ($action === self::ACTION_UPDATE) {
$payload['engagementId'] = $engagementData['crmId'];
$payload['data'] = $data;
}
if ($action === self::ACTION_DELETE) {
$payload['engagementId'] = $engagementData['crmId'];
}
$this->logger->info('[HubSpot] Engagement manipulated (' . $action . ')', $payload);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45157
|
1621
|
13
|
2026-05-14T14:23:05.379144+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768585379_m1.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:23:05* :QProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php:=custom.log> D CrmObjectsUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.phpO DecorateActivity› D Dummy• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.php xAccountController.php› HelpersT IntegrationAppTrait.php.env.staging.envDetachActivityObject.phpRematchActivityOnCrmObjectDetach.phpv Hubspot© Client.php18D AccountSyncStrate› D ActionsD ContactSyncStrate!> DDTO› O Fields› D Journal© MatchActivityCrmData.phptrait WriteCrmTrait* Othrows HubspotException* @throws BadRequest*/1 usageHubspotPaginationService.phpHandleHubspotRateLimit.php19525354A8M6AYMetadata55private function puildConferencePayload(Activity $activity): Activity56v OpportunitySyncSti> [ Concerns57$decorator = $this->getDecorateActivity®:© HubspotLastMor58© HubspotLastMor59© HubspotLastMor68© HubspotLastMor6162© HubspotLastMor© HubspotSingleS:63$engagement = ['active' = true,'ownerid' => Sthis->profile->getCrmProviderId(),'timestamp' => $decorator->formatStartTime($activity),'type' => 'MEETING',© HubspotSyncStr641:© HubspotWebhoc6566v D Pagination© HubspotPaginati67if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType))) {$engagement['activityType'] = $activity->getActivityType()->getName();© PaginationConfig68© PaginationState.6970> D ProspectSearchStra> [ Redis71v D ServiceTraits72$metadata = ['meetingOutcome' => $decorator->convertMeetingOutcome($activity),'internalMeetingNotes' => $decorator-›generateDescription(Sactivity),€ OpportunitySync73© SyncCrmEntities74+ SyncFieldsTrait./75// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a (231T WriteCrmTrait.pl76if (! $activity->hasCrmProviderId)) {D Utils77if (Sactivity->hasActualStartTime() && $activity->hasActualEndTime()) {D Webhook78Smetadata[ 'startTime'] = $decorator->formatStartTime(Sactivity);D211212213214215216217218— 219220221222223224225=226_227228229230232- 233 /234@ RatchSvneCnllertn79Smetadata['endTime'] = Sdecoraton->formatEndTime(Sactivity);Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !M crm_layout_eilIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial,1 on u.id= sa.:1..n<->1: on t.L_id = 1052 andIMaccounts wheiactivities55:22UTF-8Co 4 spaces...
|
NULL
|
155710469272411052
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:23:05* :QProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php:=custom.log> D CrmObjectsUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.phpO DecorateActivity› D Dummy• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.php xAccountController.php› HelpersT IntegrationAppTrait.php.env.staging.envDetachActivityObject.phpRematchActivityOnCrmObjectDetach.phpv Hubspot© Client.php18D AccountSyncStrate› D ActionsD ContactSyncStrate!> DDTO› O Fields› D Journal© MatchActivityCrmData.phptrait WriteCrmTrait* Othrows HubspotException* @throws BadRequest*/1 usageHubspotPaginationService.phpHandleHubspotRateLimit.php19525354A8M6AYMetadata55private function puildConferencePayload(Activity $activity): Activity56v OpportunitySyncSti> [ Concerns57$decorator = $this->getDecorateActivity®:© HubspotLastMor58© HubspotLastMor59© HubspotLastMor68© HubspotLastMor6162© HubspotLastMor© HubspotSingleS:63$engagement = ['active' = true,'ownerid' => Sthis->profile->getCrmProviderId(),'timestamp' => $decorator->formatStartTime($activity),'type' => 'MEETING',© HubspotSyncStr641:© HubspotWebhoc6566v D Pagination© HubspotPaginati67if ($activity->hasActivityType() && $this->matchesCrmType($activity->getActivityType))) {$engagement['activityType'] = $activity->getActivityType()->getName();© PaginationConfig68© PaginationState.6970> D ProspectSearchStra> [ Redis71v D ServiceTraits72$metadata = ['meetingOutcome' => $decorator->convertMeetingOutcome($activity),'internalMeetingNotes' => $decorator-›generateDescription(Sactivity),€ OpportunitySync73© SyncCrmEntities74+ SyncFieldsTrait./75// Only if they are creating a fresh engagement should we update the times, otherwise it will cause a (231T WriteCrmTrait.pl76if (! $activity->hasCrmProviderId)) {D Utils77if (Sactivity->hasActualStartTime() && $activity->hasActualEndTime()) {D Webhook78Smetadata[ 'startTime'] = $decorator->formatStartTime(Sactivity);D211212213214215216217218— 219220221222223224225=226_227228229230232- 233 /234@ RatchSvneCnllertn79Smetadata['endTime'] = Sdecoraton->formatEndTime(Sactivity);Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oim teams wherem crm_layouts !M crm_layout_eilIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial,1 on u.id= sa.:1..n<->1: on t.L_id = 1052 andIMaccounts wheiactivities55:22UTF-8Co 4 spaces...
|
45155
|
NULL
|
NULL
|
NULL
|
|
45156
|
1622
|
3
|
2026-05-14T14:22:58.942966+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768578942_m2.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterday at 13.34Yesterday at 13:34Yesterday at 13.33Yesterdav at 13:32resterday al i5.sYesterdav at 13:31Yesterday at 13:30Yesterday at 13.29Yesterday at 13:29resterday at 15.2oYesterday at 13:27Yesterday at 13:26Yesterday at 13:26Yesterday at 13:25Yesterday at 13.24Yesterdav at 13:24Yesterday at 13:23Yesterday at 13:21Yesterday at 13:21Yesterday at 13.20Yesterdav at 13:19Yesterday at 13:19Yesterday at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13.16Yecterdav at 12:16Yesterday at 13:15Yesterday at 13.10Yesterdav at 13:14Yesterday at 13:14Yesterday at 13:13Yecterdav at 12:12Yesterday at 13.11Yesterdav at 13:11Yesterday at 13:10Yesterday at 13:09Yesterday at 13:09Yesterday at 13:08Yesterday at 13.08Yecterdav at 12:07Yesterday at 13:07Yesterdav at 13:0617K:MPEG-4 movie29 KBMPEG-4 movie6 KB12 Kb9 KBIMPEG-4 movieMPEG-4 movie7 KB8 KBMPEG-4 movie37 K:10 KBMPEG-4 movie7 KBMPEG-4 movie9 KBMPEG-4 movie8 KB72 KBMPEG-4 movie14 K:13 KBMPEG-4 movie9 KB18 KB|MPEG-4 movie12 KBMPEG-4 movie10 KB16 KBMPEG-4 movie6KEMPEG-4 movie6 KB MPEG-4 movie12 KB23 K:MPEG-4 movie8 KBMPEG-4 movie6 KBMPEG-4 movie11 KEMPEG-4 movie11 KBMPEG-4 movie20 KB34 K:MPEG-4 movie10 KBMPEG-4 movie7 KB5KBMPEG-4 movie11 KPMPEG-4 movie26 KB MPEG-4 movie111 KBMPEG-4 movie102 K:MPEG-4 movie88 KBMPEG-4 movie59 KB98 KBMPEG-4 movie07 KPMDEG-A movie66 KBMPEG-4 movie44 KBMPEG-4 movie03 K:IMPEG-A movid78 KB MPEG-4 movie50 KB58 KB27 KPMPEG-4 movieMPEG-4 movie7 KB12 KBMPEG-4 movie22 K:17 KBMPEG-4 movie19 KB32 K8MPEG-4 movieFavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-ywJo.ziPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dmaimage.jpg- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.63 GB availabld• Inu 14 May 1/.L2:00Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
4675722753822127110
|
NULL
|
click
|
ocr
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterday at 13.34Yesterday at 13:34Yesterday at 13.33Yesterdav at 13:32resterday al i5.sYesterdav at 13:31Yesterday at 13:30Yesterday at 13.29Yesterday at 13:29resterday at 15.2oYesterday at 13:27Yesterday at 13:26Yesterday at 13:26Yesterday at 13:25Yesterday at 13.24Yesterdav at 13:24Yesterday at 13:23Yesterday at 13:21Yesterday at 13:21Yesterday at 13.20Yesterdav at 13:19Yesterday at 13:19Yesterday at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13.16Yecterdav at 12:16Yesterday at 13:15Yesterday at 13.10Yesterdav at 13:14Yesterday at 13:14Yesterday at 13:13Yecterdav at 12:12Yesterday at 13.11Yesterdav at 13:11Yesterday at 13:10Yesterday at 13:09Yesterday at 13:09Yesterday at 13:08Yesterday at 13.08Yecterdav at 12:07Yesterday at 13:07Yesterdav at 13:0617K:MPEG-4 movie29 KBMPEG-4 movie6 KB12 Kb9 KBIMPEG-4 movieMPEG-4 movie7 KB8 KBMPEG-4 movie37 K:10 KBMPEG-4 movie7 KBMPEG-4 movie9 KBMPEG-4 movie8 KB72 KBMPEG-4 movie14 K:13 KBMPEG-4 movie9 KB18 KB|MPEG-4 movie12 KBMPEG-4 movie10 KB16 KBMPEG-4 movie6KEMPEG-4 movie6 KB MPEG-4 movie12 KB23 K:MPEG-4 movie8 KBMPEG-4 movie6 KBMPEG-4 movie11 KEMPEG-4 movie11 KBMPEG-4 movie20 KB34 K:MPEG-4 movie10 KBMPEG-4 movie7 KB5KBMPEG-4 movie11 KPMPEG-4 movie26 KB MPEG-4 movie111 KBMPEG-4 movie102 K:MPEG-4 movie88 KBMPEG-4 movie59 KB98 KBMPEG-4 movie07 KPMDEG-A movie66 KBMPEG-4 movie44 KBMPEG-4 movie03 K:IMPEG-A movid78 KB MPEG-4 movie50 KB58 KB27 KPMPEG-4 movieMPEG-4 movie7 KB12 KBMPEG-4 movie22 K:17 KBMPEG-4 movie19 KB32 K8MPEG-4 movieFavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-ywJo.ziPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dmaimage.jpg- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.63 GB availabld• Inu 14 May 1/.L2:00Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
45152
|
NULL
|
NULL
|
NULL
|
|
45155
|
1621
|
12
|
2026-05-14T14:22:58.920709+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768578920_m1.jpg...
|
PhpStorm
|
faVsco.js – WriteCrmTrait.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% (C47•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest* :Project v8• Thu 14 May 17:22:58Q© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php=custom.log> D CrmObjects© UserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php• DecorateActivity› D Dummy• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.php› HelpersT IntegrationAppTrait.php.env.staging.envDetachActivityObject.phpv HubspotClient.php18D AccountSyncStrate› DJ Actions1921D ContactSyncStrate!› O DTO› O Fields› D Journal© MatchActivityCrmData.phptrait WriteCrmTraitprivate const string ACTION_CREATE = 'create' :2 usages2 usages© HubspotPaginationService.php22private const string ACTION_UPDATE = 'update' ;23Metadataprivate const string ACTION_DELETE = 'delete';24v OpportunitySyncSti> [ Concerns25© HubspotLastMor26© HubspotLastMor27/***/* @inheritdoc© HubspotLastMor28 €public function saveActivity(Activity $activity): Activity© HubspotLastMor2930© HubspotLastMor31© HubspotSingleS:© HubspotSyncStr32switch ($activity->getCrmType)) {case Activity:: TYPE_CONFERENCE:Sactivity = $this->buildConferencePayload(Sactivity);© HubspotWebhoc33v D Pagination34© HubspotPaginati35© PaginationConfig36© PaginationState.37break;case Activity:: TYPE_SOFTPHONE:case Activity::TYPE_SOFTPHONE_INBOUND:Sactivity = $this->buildSoftphonePayload($activity);> D ProspectSearchStra38› [ Redis39break;v D ServiceTraits40€ OpportunitySync41© SyncCrmEntities42+ SyncFieldsTrait./43case Activity::TYPE_SMS_INBOUND:case Activity: : TYPE_SMS_OUTBOUND:Sactivity = $this->buildTextMessagePayload($activity);T WriteCrmTrait.pl44D Utils45break;D Webhook46@ RatchSvnrCnllertn'47Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)SendReportJob.php=laravel.logT WriteCrmTrait.php xAccountController.phpSF [jiminny@localhost]RematchActivityOnCrmObjectDetach.phpA HS_local [jiminny@localho:WHandleHubspotRateLimit.php4 console [QAI PROD] XA7 AV4 console [PROD]A console (EU]DGo jiminny08A1 43M4AY211m migrations oi212-213214215— 216m teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wi217218219220m features;m team_feature:m opportunitie:221222m teams;223224.id, CASEWHEN=225— 226227228229230,id FROM social,1 on V.id = sa.:1..n<->1: on t.Lid = 1052 and231232233 VIMaccounts wheiactivities234W Windsurf Teams28:21UTF-8Co 4 spaces...
|
NULL
|
-6457976466920580779
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% (C47•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest* :Project v8• Thu 14 May 17:22:58Q© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php=custom.log> D CrmObjects© UserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php• DecorateActivity› D Dummy• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.php› HelpersT IntegrationAppTrait.php.env.staging.envDetachActivityObject.phpv HubspotClient.php18D AccountSyncStrate› DJ Actions1921D ContactSyncStrate!› O DTO› O Fields› D Journal© MatchActivityCrmData.phptrait WriteCrmTraitprivate const string ACTION_CREATE = 'create' :2 usages2 usages© HubspotPaginationService.php22private const string ACTION_UPDATE = 'update' ;23Metadataprivate const string ACTION_DELETE = 'delete';24v OpportunitySyncSti> [ Concerns25© HubspotLastMor26© HubspotLastMor27/***/* @inheritdoc© HubspotLastMor28 €public function saveActivity(Activity $activity): Activity© HubspotLastMor2930© HubspotLastMor31© HubspotSingleS:© HubspotSyncStr32switch ($activity->getCrmType)) {case Activity:: TYPE_CONFERENCE:Sactivity = $this->buildConferencePayload(Sactivity);© HubspotWebhoc33v D Pagination34© HubspotPaginati35© PaginationConfig36© PaginationState.37break;case Activity:: TYPE_SOFTPHONE:case Activity::TYPE_SOFTPHONE_INBOUND:Sactivity = $this->buildSoftphonePayload($activity);> D ProspectSearchStra38› [ Redis39break;v D ServiceTraits40€ OpportunitySync41© SyncCrmEntities42+ SyncFieldsTrait./43case Activity::TYPE_SMS_INBOUND:case Activity: : TYPE_SMS_OUTBOUND:Sactivity = $this->buildTextMessagePayload($activity);T WriteCrmTrait.pl44D Utils45break;D Webhook46@ RatchSvnrCnllertn'47Workspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)SendReportJob.php=laravel.logT WriteCrmTrait.php xAccountController.phpSF [jiminny@localhost]RematchActivityOnCrmObjectDetach.phpA HS_local [jiminny@localho:WHandleHubspotRateLimit.php4 console [QAI PROD] XA7 AV4 console [PROD]A console (EU]DGo jiminny08A1 43M4AY211m migrations oi212-213214215— 216m teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wi217218219220m features;m team_feature:m opportunitie:221222m teams;223224.id, CASEWHEN=225— 226227228229230,id FROM social,1 on V.id = sa.:1..n<->1: on t.Lid = 1052 and231232233 VIMaccounts wheiactivities234W Windsurf Teams28:21UTF-8Co 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45154
|
1621
|
11
|
2026-05-14T14:22:57.279229+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768577279_m1.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
s
Inherited members (⌘R)
Anonymous Classes (⌘I)
La s
Inherited members (⌘R)
Anonymous Classes (⌘I)
Lambdas (⌘L)
WriteCrmTrait
ACTION_CREATE: string = 'create', private
ACTION_DELETE: string = 'delete', private
ACTION_UPDATE: string = 'update', private
buildAssociation(id: int, categoryToTypeIds: array): array, private method
buildAssociationType(category: string, typeId: int): array, private method
buildSoftphonePayload(activity: Activity): Activity, private method
buildTextMessagePayload(activity: Activity): Activity, private method
convertActivityMeetingAssociationsV4(activity: Activity): array, private method
createMeetingV3(engagement: array, associations: array, metadata: array): Response, private method
fetchCustomFieldData(activity: Activity, objectType: string): array, private method
getActivityAssociations(activity: Activity): array, private method
getAssociationDifferences(activity: Activity, oldAssociations: array, currentAssociations: array): array, private method
hasEngagementActivityType(engagementId: string): bool, private method
logCrmEngagementManipulation(action: string, engagementData: array, [data: array = [...]], [associations: array = [...]]): void, private method
normalizeIds(ids: array): array, private method
saveActivity(activity: Activity): Activity ↑RemoteEntityManipulationInterface, public method
saveFollowupActivity(activity: Activity, fields: array): null|string ↑RemoteEntityManipulationInterface, public method
shouldIncludeRemovedAssociations(type: string, added: array, activity: Activity): bool, private method
updateActivityAssociations(activity: Activity, oldAssociations: array): void, private method
updateAssociations(activity: Activity, associationChanges: array): void, private method
updateMeetingV3(meetingId: string, engagement: array, metadata: array): Response, private method
updateNonTaskActivity(activity: Activity, engagement: array, metadata: array, oldAssociations: array): void, private method
updateTask(activity: Activity, engagement: array, metadata: array): void, private method
upsertActivity(activity: Activity, engagement: array, metadata: array): Activity, method
ACTION_CREATE: string = 'create', private
ACTION_DELETE: string = 'delete', private...
|
[{"role":"AXTextField","text [{"role":"AXTextField","text":"s","depth":1,"bounds":{"left":0.52152777,"top":0.32,"width":0.06458333,"height":0.031111112},"on_screen":true,"value":"s","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Inherited members (⌘R)","depth":1,"bounds":{"left":0.5277778,"top":0.35555556,"width":0.10972222,"height":0.031111112},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Anonymous Classes (⌘I)","depth":1,"bounds":{"left":0.64444447,"top":0.35555556,"width":0.10972222,"height":0.031111112},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Lambdas (⌘L)","depth":1,"bounds":{"left":0.76111114,"top":0.35555556,"width":0.10972222,"height":0.031111112},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"WriteCrmTrait","depth":4,"bounds":{"left":0.5395833,"top":0.16777778,"width":0.077083334,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ACTION_CREATE: string = 'create', private","depth":5,"bounds":{"left":0.55277777,"top":0.19222222,"width":0.1736111,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ACTION_DELETE: string = 'delete', private","depth":5,"bounds":{"left":0.55277777,"top":0.21666667,"width":0.17152777,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ACTION_UPDATE: string = 'update', private","depth":5,"bounds":{"left":0.55277777,"top":0.24111111,"width":0.17708333,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"buildAssociation(id: int, categoryToTypeIds: array): array, private method","depth":5,"bounds":{"left":0.55277777,"top":0.26555556,"width":0.27083334,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"buildAssociationType(category: string, typeId: int): array, private method","depth":5,"bounds":{"left":0.55277777,"top":0.29,"width":0.26805556,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"buildSoftphonePayload(activity: Activity): Activity, private method","depth":5,"bounds":{"left":0.55277777,"top":0.31444445,"width":0.23888889,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"buildTextMessagePayload(activity: Activity): Activity, private method","depth":5,"bounds":{"left":0.55277777,"top":0.33888888,"width":0.25277779,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"convertActivityMeetingAssociationsV4(activity: Activity): array, private method","depth":5,"bounds":{"left":0.55277777,"top":0.36333334,"width":0.2951389,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"createMeetingV3(engagement: array, associations: array, metadata: array): Response, private method","depth":5,"bounds":{"left":0.55277777,"top":0.38777778,"width":0.39375,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"fetchCustomFieldData(activity: Activity, objectType: string): array, private method","depth":5,"bounds":{"left":0.55277777,"top":0.41222224,"width":0.30833334,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"getActivityAssociations(activity: Activity): array, private method","depth":5,"bounds":{"left":0.55277777,"top":0.43666667,"width":0.22986111,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"getAssociationDifferences(activity: Activity, oldAssociations: array, currentAssociations: array): array, private method","depth":5,"bounds":{"left":0.55277777,"top":0.4611111,"width":0.44722223,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"hasEngagementActivityType(engagementId: string): bool, private method","depth":5,"bounds":{"left":0.55277777,"top":0.48555556,"width":0.27152777,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"logCrmEngagementManipulation(action: string, engagementData: array, [data: array = [...]], [associations: array = [...]]): void, private method","depth":5,"bounds":{"left":0.55277777,"top":0.51,"width":0.44722223,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"normalizeIds(ids: array): array, private method","depth":5,"bounds":{"left":0.55277777,"top":0.53444445,"width":0.15486111,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"saveActivity(activity: Activity): Activity ↑RemoteEntityManipulationInterface, public method","depth":5,"bounds":{"left":0.55277777,"top":0.5588889,"width":0.3548611,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"saveFollowupActivity(activity: Activity, fields: array): null|string ↑RemoteEntityManipulationInterface, public method","depth":5,"bounds":{"left":0.55277777,"top":0.5833333,"width":0.44722223,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"shouldIncludeRemovedAssociations(type: string, added: array, activity: Activity): bool, private method","depth":5,"bounds":{"left":0.55277777,"top":0.6077778,"width":0.3923611,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"updateActivityAssociations(activity: Activity, oldAssociations: array): void, private method","depth":5,"bounds":{"left":0.55277777,"top":0.63222224,"width":0.34097221,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"updateAssociations(activity: Activity, associationChanges: array): void, private method","depth":5,"bounds":{"left":0.55277777,"top":0.6566667,"width":0.32777777,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"updateMeetingV3(meetingId: string, engagement: array, metadata: array): Response, private method","depth":5,"bounds":{"left":0.55277777,"top":0.6811111,"width":0.38819444,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"updateNonTaskActivity(activity: Activity, engagement: array, metadata: array, oldAssociations: array): void, private method","depth":5,"bounds":{"left":0.55277777,"top":0.70555556,"width":0.44722223,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"updateTask(activity: Activity, engagement: array, metadata: array): void, private method","depth":5,"bounds":{"left":0.55277777,"top":0.73,"width":0.33472222,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"upsertActivity(activity: Activity, engagement: array, metadata: array): Activity, method","depth":5,"bounds":{"left":0.55277777,"top":0.7544444,"width":0.34652779,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ACTION_CREATE: string = 'create', private","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.1736111,"height":0.024444444},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"ACTION_DELETE: string = 'delete', private","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.17152777,"height":0.024444444},"on_screen":false,"role_description":"text"}]...
|
7231423580236642576
|
8728989992795289067
|
visual_change
|
accessibility
|
NULL
|
s
Inherited members (⌘R)
Anonymous Classes (⌘I)
La s
Inherited members (⌘R)
Anonymous Classes (⌘I)
Lambdas (⌘L)
WriteCrmTrait
ACTION_CREATE: string = 'create', private
ACTION_DELETE: string = 'delete', private
ACTION_UPDATE: string = 'update', private
buildAssociation(id: int, categoryToTypeIds: array): array, private method
buildAssociationType(category: string, typeId: int): array, private method
buildSoftphonePayload(activity: Activity): Activity, private method
buildTextMessagePayload(activity: Activity): Activity, private method
convertActivityMeetingAssociationsV4(activity: Activity): array, private method
createMeetingV3(engagement: array, associations: array, metadata: array): Response, private method
fetchCustomFieldData(activity: Activity, objectType: string): array, private method
getActivityAssociations(activity: Activity): array, private method
getAssociationDifferences(activity: Activity, oldAssociations: array, currentAssociations: array): array, private method
hasEngagementActivityType(engagementId: string): bool, private method
logCrmEngagementManipulation(action: string, engagementData: array, [data: array = [...]], [associations: array = [...]]): void, private method
normalizeIds(ids: array): array, private method
saveActivity(activity: Activity): Activity ↑RemoteEntityManipulationInterface, public method
saveFollowupActivity(activity: Activity, fields: array): null|string ↑RemoteEntityManipulationInterface, public method
shouldIncludeRemovedAssociations(type: string, added: array, activity: Activity): bool, private method
updateActivityAssociations(activity: Activity, oldAssociations: array): void, private method
updateAssociations(activity: Activity, associationChanges: array): void, private method
updateMeetingV3(meetingId: string, engagement: array, metadata: array): Response, private method
updateNonTaskActivity(activity: Activity, engagement: array, metadata: array, oldAssociations: array): void, private method
updateTask(activity: Activity, engagement: array, metadata: array): void, private method
upsertActivity(activity: Activity, engagement: array, metadata: array): Activity, method
ACTION_CREATE: string = 'create', private
ACTION_DELETE: string = 'delete', private...
|
45153
|
NULL
|
NULL
|
NULL
|
|
45153
|
1621
|
10
|
2026-05-14T14:22:54.243568+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768574243_m1.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
saave
Inherited members (⌘R)
Anonymous Classes (⌘I saave
Inherited members (⌘R)
Anonymous Classes (⌘I)
Lambdas (⌘L)
WriteCrmTrait.php...
|
[{"role":"AXTextField","text [{"role":"AXTextField","text":"saave","depth":1,"bounds":{"left":0.52152777,"top":0.32,"width":0.06458333,"height":0.031111112},"on_screen":true,"value":"saave","role_description":"text field","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Inherited members (⌘R)","depth":1,"bounds":{"left":0.5277778,"top":0.35555556,"width":0.10972222,"height":0.031111112},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Anonymous Classes (⌘I)","depth":1,"bounds":{"left":0.64444447,"top":0.35555556,"width":0.10972222,"height":0.031111112},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXCheckBox","text":"Lambdas (⌘L)","depth":1,"bounds":{"left":0.76111114,"top":0.35555556,"width":0.10972222,"height":0.031111112},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"WriteCrmTrait.php","depth":1,"bounds":{"left":0.5277778,"top":0.3188889,"width":0.35277778,"height":0.036666665},"on_screen":true,"role_description":"text"}]...
|
-6236990536150617012
|
938158309487346305
|
visual_change
|
hybrid
|
NULL
|
saave
Inherited members (⌘R)
Anonymous Classes (⌘I saave
Inherited members (⌘R)
Anonymous Classes (⌘I)
Lambdas (⌘L)
WriteCrmTrait.php
PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelplhlFV faVsco.jsv#12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestvProject v100% С8• Thu 14 May 17:22:54Q© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php:=custom.log> D CrmObjectsUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php• DecorateActivity› D Dummy• DeleteCrmEntityTrait.phpDeleteAccountJob.php© ImportActivityTypes.phpT WriteCrmTrait.php X© AccountController.php› HelpersT IntegrationAppTrait.php=.env.staging.envDetachActivityObject.phpRematchActivityOnCrmObjectDetach.phpv Hubspot© MatchActivityCrmData.php© Client.php© HubspotPaginationService.phpHandleHubspotRateLimit.php18D AccountSyncStrate› DJ Actions12<? phpA7 . vD ContactSyncStrate!> DDTOdeclare(strict_types=1):› OJ FieldsQsaaveWriteCrmTrait.php› D Journalnamespace Jiminny\Services\Crm\Hubspot\ServiceTraInherited members (28R)Anonymous Classes (81)Lambdas (2L)Metadatav OpportunitySyncStiUse> [ Concerns© HubspotLastMor1819 @20trait WriteCrmTrait© HubspotLastMor{© HubspotLastMor© HubspotLastMor21© HubspotLastMor22© HubspotSingleS:© HubspotSyncStr4 usages2 usages2 usages"saave' not foundprivate const string ACTION_CREATE = 'create'private const string ACTION_UPDATE = 'update'© HubspotWebhocv D Pagination© HubspotPaginati© PaginationConfig© PaginationState.> D ProspectSearchStra> D Redisv D ServiceTraits€ OpportunitySync© SyncCrmEntities+ SyncFieldsTrait./232425262728 € ›5051525354private const string ACTION_DELETE = 'delete'/***/* @inheritdocpublic function saveActivity(Activity $activity): Activity{…..}T WriteCrmTrait.pl/*** @throws HubspotException* Othrows BadRequest*/1 usageD Utils5589private function buildConferencePayload(Activity $activity): Activity{...}D Webhook@ RatchSvneCnllertn'2 usagesWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console (PROD]A console (EU]Go jiminnyA3X4 A Vmmigrations oim teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHEN226227228229230231232233 V234id FROM social,1 on V.id = sa.:1..n<->1: on t.Lid = 1052 andIMaccounts wheiactivitiesW Windsurf Teams1:1UTF-8Co 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45152
|
1622
|
2
|
2026-05-14T14:22:45.653507+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768565653_m2.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIđ 0Pm~ (Q SearchDate ModifiedYesterdav at 13.34Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:32Yesterday at 13:31Yesterdav at 13:30Yesterday at 13:30Yesterday at 13.29Yesterday at 13:28resterday at 15.21Yesterdav at 13:27Yesterday at 13:26Yesterday at 13:26Yesterday at 13:23Yesterday at 13:25Yesterday at 13.24Yesterdav at 13:23Yesterday at 13:22Testerady dl ls.2.Yesterday at 13:21Yesterday at 13:20Yesterday at 13.19Yesterdav at 13:19Yesterday at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.16Yecterdav at 12:15Yesterday at 13:15Yesterday at 13-14Yesterdav at 13:14Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:12Yesterday at 13.11Yesterdav at 13:10Yesterday at 13:10Yesterday at 13:09Yoctorday at 12:09Yesterday at 13:08Yesterday at 13.0Yecterdav at 12:07Yesterday at 13:06Yesterdav at 13:0529 K:MPEG-4 movie6 KBMPEG-4 movie12 KBMPEG-4 movieMPEG-4 movie7 KBI8 KB37 KBMPEG-4 movie10 K:7 KBMPEG-4 movie8 KBMPEG-4 movie8 KBMPEG-4 movie72 KB14 KBMPEG-4 movie13 KE9KBMPEG-4 movie18 KB12 KB|10 KRIMPEG-4 movieMPEG-4 movie16 KB6 KBMPEG-4 movie6KEMPEG-4 movie12 KBMPEG-4 movie23 KB8 K:MPEG-4 movie6 KBMPEG-4 movie6 KB11 KBMPEG-4 movie11 KEMPEG-4 movie20 KBMPEG-4 movie34 KB10 K:MPEG-4 movie7 KBMPEG-4 movie5 KB11 KBMPEG-4 movie26KPMPEG-4 movie111 KB MPEG-4 movie102 KB88 KBMPEG-4 movie59 KBMPEG-4 movie98 KB97 KBRAKRMPEG-4 movieMDEG-A movie44 KB93 KBMPEG-4 movie78 K:MPEG-A movie50 KBMPEG-4 movie58 KB27 KB7 KPMPEG-4 movieMPEG-4 movie12 KB32 KBMPEG-4 movie17 Kг19 KBMPEG-4 movie32 KB10KBMPEG-4 movieAl Notes: OffLeave• 0FavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network_• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-yWJo.zioPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dmaimage.jpg- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pa• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.64 GB availabld• Inu 14 Mау 1/•22.42Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
2030629860205763140
|
NULL
|
app_switch
|
ocr
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIđ 0Pm~ (Q SearchDate ModifiedYesterdav at 13.34Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:32Yesterday at 13:31Yesterdav at 13:30Yesterday at 13:30Yesterday at 13.29Yesterday at 13:28resterday at 15.21Yesterdav at 13:27Yesterday at 13:26Yesterday at 13:26Yesterday at 13:23Yesterday at 13:25Yesterday at 13.24Yesterdav at 13:23Yesterday at 13:22Testerady dl ls.2.Yesterday at 13:21Yesterday at 13:20Yesterday at 13.19Yesterdav at 13:19Yesterday at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.16Yecterdav at 12:15Yesterday at 13:15Yesterday at 13-14Yesterdav at 13:14Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:12Yesterday at 13.11Yesterdav at 13:10Yesterday at 13:10Yesterday at 13:09Yoctorday at 12:09Yesterday at 13:08Yesterday at 13.0Yecterdav at 12:07Yesterday at 13:06Yesterdav at 13:0529 K:MPEG-4 movie6 KBMPEG-4 movie12 KBMPEG-4 movieMPEG-4 movie7 KBI8 KB37 KBMPEG-4 movie10 K:7 KBMPEG-4 movie8 KBMPEG-4 movie8 KBMPEG-4 movie72 KB14 KBMPEG-4 movie13 KE9KBMPEG-4 movie18 KB12 KB|10 KRIMPEG-4 movieMPEG-4 movie16 KB6 KBMPEG-4 movie6KEMPEG-4 movie12 KBMPEG-4 movie23 KB8 K:MPEG-4 movie6 KBMPEG-4 movie6 KB11 KBMPEG-4 movie11 KEMPEG-4 movie20 KBMPEG-4 movie34 KB10 K:MPEG-4 movie7 KBMPEG-4 movie5 KB11 KBMPEG-4 movie26KPMPEG-4 movie111 KB MPEG-4 movie102 KB88 KBMPEG-4 movie59 KBMPEG-4 movie98 KB97 KBRAKRMPEG-4 movieMDEG-A movie44 KB93 KBMPEG-4 movie78 K:MPEG-A movie50 KBMPEG-4 movie58 KB27 KB7 KPMPEG-4 movieMPEG-4 movie12 KB32 KBMPEG-4 movie17 Kг19 KBMPEG-4 movie32 KB10KBMPEG-4 movieAl Notes: OffLeave• 0FavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network_• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-yWJo.zioPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dmaimage.jpg- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pa• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.64 GB availabld• Inu 14 Mау 1/•22.42Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45151
|
1621
|
9
|
2026-05-14T14:22:48.181636+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768568181_m1.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project Files
Preview
Filter
Open in Find Tool Win Project Files
Preview
Filter
Open in Find Tool Window
Impor
ImportActivityTypes.php .../app/Listeners/Crm/ImportActivityTypes.php, class
ImportBatchJobTrait.php .../app/Jobs/Crm/Hubspot/ImportBatchJobTrait.php
ImportCall.php .../app/Jobs/Activity/Import/ImportCall.php, class
ImportActivityTypesTest.php .../tests/Unit/Listeners/Crm/ImportActivityTypesTest.php, class
ImportAccountBatch.php .../app/Jobs/Crm/Hubspot/ImportAccountBatch.php, class
ImportCallsCommand.php .../app/Console/Commands/Dev/ImportCallsCommand.php, class
ImportCallTest.php .../tests/Unit/Jobs/Activity/Import/ImportCallTest.php, final class
ImportContactBatch.php .../app/Jobs/Crm/Hubspot/ImportContactBatch.php, class
ImportBotRecordingJob.php .../app/Services/RecallAI/Jobs/ImportBotRecordingJob.php, class
ImportAccountBatchTest.php .../tests/Unit/Jobs/Crm/ImportAccountBatchTest.php, class
ImportContactBatchTest.php .../tests/Unit/Jobs/Crm/ImportContactBatchTest.php, class
ImportBotRecordingJobTest.php .../tests/Unit/Services/RecallAI/Jobs/ImportBotRecordingJobTest.php, class
ImportCall.php.html build/coverage/Jobs/Activity/Import
ImportActivityTypes.php.html build/coverage/Listeners/Crm
ImportCallsCommand.php.html build/coverage/Console/Commands/Dev
… more
ImportActivityTypes.php .../app/Listeners/Crm/ImportActivityTypes.php, class
ImportBatchJobTrait.php .../app/Jobs/Crm/Hubspot/ImportBatchJobTrait.php
ImportCall.php .../app/Jobs/Activity/Import/ImportCall.php, class
ImportActivityTypesTest.php .../tests/Unit/Listeners/Crm/ImportActivityTypesTest.php, class
ImportAccountBatch.php .../app/Jobs/Crm/Hubspot/ImportAccountBatch.php, class
ImportCallsCommand.php .../app/Console/Commands/Dev/ImportCallsCommand.php, class
ImportCallTest.php .../tests/Unit/Jobs/Activity/Import/ImportCallTest.php, final class
ImportContactBatch.php .../app/Jobs/Crm/Hubspot/ImportContactBatch.php, class
ImportBotRecordingJob.php .../app/Services/RecallAI/Jobs/ImportBotRecordingJob.php, class
ImportAccountBatchTest.php .../tests/Unit/Jobs/Crm/ImportAccountBatchTest.php, class
ImportContactBatchTest.php .../tests/Unit/Jobs/Crm/ImportContactBatchTest.php, class
ImportBotRecordingJobTest.php .../tests/Unit/Services/RecallAI/Jobs/ImportBotRecordingJobTest.php, class
ImportCall.php.html build/coverage/Jobs/Activity/Import
ImportActivityTypes.php.html build/coverage/Listeners/Crm
ImportCallsCommand.php.html build/coverage/Console/Commands/Dev
… more
Listeners/Crm/ImportActivityTypes.php
Open In Right Split...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project Files","depth":2,"bounds":{"left":0.8298611,"top":0.25,"width":0.07430556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Preview","depth":2,"bounds":{"left":0.90416664,"top":0.25,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter","depth":2,"bounds":{"left":0.9222222,"top":0.25,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Find Tool Window","depth":2,"bounds":{"left":0.94027776,"top":0.25,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"Impor","depth":1,"bounds":{"left":0.50555557,"top":0.29222223,"width":0.45277777,"height":0.032222223},"on_screen":true,"value":"Impor","role_description":"text field","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"ImportActivityTypes.php .../app/Listeners/Crm/ImportActivityTypes.php, class","depth":2,"bounds":{"left":0.49930555,"top":0.33666667,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportBatchJobTrait.php .../app/Jobs/Crm/Hubspot/ImportBatchJobTrait.php","depth":2,"bounds":{"left":0.49930555,"top":0.3611111,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportCall.php .../app/Jobs/Activity/Import/ImportCall.php, class","depth":2,"bounds":{"left":0.49930555,"top":0.38555557,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportActivityTypesTest.php .../tests/Unit/Listeners/Crm/ImportActivityTypesTest.php, class","depth":2,"bounds":{"left":0.49930555,"top":0.41,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportAccountBatch.php .../app/Jobs/Crm/Hubspot/ImportAccountBatch.php, class","depth":2,"bounds":{"left":0.49930555,"top":0.43444446,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportCallsCommand.php .../app/Console/Commands/Dev/ImportCallsCommand.php, class","depth":2,"bounds":{"left":0.49930555,"top":0.4588889,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportCallTest.php .../tests/Unit/Jobs/Activity/Import/ImportCallTest.php, final class","depth":2,"bounds":{"left":0.49930555,"top":0.48333332,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportContactBatch.php .../app/Jobs/Crm/Hubspot/ImportContactBatch.php, class","depth":2,"bounds":{"left":0.49930555,"top":0.50777775,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportBotRecordingJob.php .../app/Services/RecallAI/Jobs/ImportBotRecordingJob.php, class","depth":2,"bounds":{"left":0.49930555,"top":0.5322222,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportAccountBatchTest.php .../tests/Unit/Jobs/Crm/ImportAccountBatchTest.php, class","depth":2,"bounds":{"left":0.49930555,"top":0.5566667,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportContactBatchTest.php .../tests/Unit/Jobs/Crm/ImportContactBatchTest.php, class","depth":2,"bounds":{"left":0.49930555,"top":0.58111113,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportBotRecordingJobTest.php .../tests/Unit/Services/RecallAI/Jobs/ImportBotRecordingJobTest.php, class","depth":2,"bounds":{"left":0.49930555,"top":0.60555553,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportCall.php.html build/coverage/Jobs/Activity/Import","depth":2,"bounds":{"left":0.49930555,"top":0.63,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportActivityTypes.php.html build/coverage/Listeners/Crm","depth":2,"bounds":{"left":0.49930555,"top":0.65444446,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportCallsCommand.php.html build/coverage/Console/Commands/Dev","depth":2,"bounds":{"left":0.49930555,"top":0.6788889,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"… more","depth":2,"bounds":{"left":0.49930555,"top":0.7033333,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportActivityTypes.php .../app/Listeners/Crm/ImportActivityTypes.php, class","depth":4,"bounds":{"left":0.49930555,"top":0.33666667,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportBatchJobTrait.php .../app/Jobs/Crm/Hubspot/ImportBatchJobTrait.php","depth":4,"bounds":{"left":0.49930555,"top":0.3611111,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportCall.php .../app/Jobs/Activity/Import/ImportCall.php, class","depth":4,"bounds":{"left":0.49930555,"top":0.38555557,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportActivityTypesTest.php .../tests/Unit/Listeners/Crm/ImportActivityTypesTest.php, class","depth":4,"bounds":{"left":0.49930555,"top":0.41,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportAccountBatch.php .../app/Jobs/Crm/Hubspot/ImportAccountBatch.php, class","depth":4,"bounds":{"left":0.49930555,"top":0.43444446,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportCallsCommand.php .../app/Console/Commands/Dev/ImportCallsCommand.php, class","depth":4,"bounds":{"left":0.49930555,"top":0.4588889,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportCallTest.php .../tests/Unit/Jobs/Activity/Import/ImportCallTest.php, final class","depth":4,"bounds":{"left":0.49930555,"top":0.48333332,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportContactBatch.php .../app/Jobs/Crm/Hubspot/ImportContactBatch.php, class","depth":4,"bounds":{"left":0.49930555,"top":0.50777775,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportBotRecordingJob.php .../app/Services/RecallAI/Jobs/ImportBotRecordingJob.php, class","depth":4,"bounds":{"left":0.49930555,"top":0.5322222,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportAccountBatchTest.php .../tests/Unit/Jobs/Crm/ImportAccountBatchTest.php, class","depth":4,"bounds":{"left":0.49930555,"top":0.5566667,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportContactBatchTest.php .../tests/Unit/Jobs/Crm/ImportContactBatchTest.php, class","depth":4,"bounds":{"left":0.49930555,"top":0.58111113,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportBotRecordingJobTest.php .../tests/Unit/Services/RecallAI/Jobs/ImportBotRecordingJobTest.php, class","depth":4,"bounds":{"left":0.49930555,"top":0.60555553,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportCall.php.html build/coverage/Jobs/Activity/Import","depth":4,"bounds":{"left":0.49930555,"top":0.63,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportActivityTypes.php.html build/coverage/Listeners/Crm","depth":4,"bounds":{"left":0.49930555,"top":0.65444446,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ImportCallsCommand.php.html build/coverage/Console/Commands/Dev","depth":4,"bounds":{"left":0.49930555,"top":0.6788889,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"… more","depth":4,"bounds":{"left":0.49930555,"top":0.7033333,"width":0.4652778,"height":0.024444444},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Listeners/Crm/ImportActivityTypes.php","depth":1,"bounds":{"left":0.51319444,"top":0.74777776,"width":0.15416667,"height":0.018888889},"on_screen":true,"help_text":"Listeners/Crm/ImportActivityTypes.php","role_description":"text"},{"role":"AXLink","text":"Open In Right Split","depth":1,"bounds":{"left":0.8673611,"top":0.74777776,"width":0.08055556,"height":0.018888889},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7492745212563973318
|
-176829527558906079
|
visual_change
|
accessibility
|
NULL
|
Project Files
Preview
Filter
Open in Find Tool Win Project Files
Preview
Filter
Open in Find Tool Window
Impor
ImportActivityTypes.php .../app/Listeners/Crm/ImportActivityTypes.php, class
ImportBatchJobTrait.php .../app/Jobs/Crm/Hubspot/ImportBatchJobTrait.php
ImportCall.php .../app/Jobs/Activity/Import/ImportCall.php, class
ImportActivityTypesTest.php .../tests/Unit/Listeners/Crm/ImportActivityTypesTest.php, class
ImportAccountBatch.php .../app/Jobs/Crm/Hubspot/ImportAccountBatch.php, class
ImportCallsCommand.php .../app/Console/Commands/Dev/ImportCallsCommand.php, class
ImportCallTest.php .../tests/Unit/Jobs/Activity/Import/ImportCallTest.php, final class
ImportContactBatch.php .../app/Jobs/Crm/Hubspot/ImportContactBatch.php, class
ImportBotRecordingJob.php .../app/Services/RecallAI/Jobs/ImportBotRecordingJob.php, class
ImportAccountBatchTest.php .../tests/Unit/Jobs/Crm/ImportAccountBatchTest.php, class
ImportContactBatchTest.php .../tests/Unit/Jobs/Crm/ImportContactBatchTest.php, class
ImportBotRecordingJobTest.php .../tests/Unit/Services/RecallAI/Jobs/ImportBotRecordingJobTest.php, class
ImportCall.php.html build/coverage/Jobs/Activity/Import
ImportActivityTypes.php.html build/coverage/Listeners/Crm
ImportCallsCommand.php.html build/coverage/Console/Commands/Dev
… more
ImportActivityTypes.php .../app/Listeners/Crm/ImportActivityTypes.php, class
ImportBatchJobTrait.php .../app/Jobs/Crm/Hubspot/ImportBatchJobTrait.php
ImportCall.php .../app/Jobs/Activity/Import/ImportCall.php, class
ImportActivityTypesTest.php .../tests/Unit/Listeners/Crm/ImportActivityTypesTest.php, class
ImportAccountBatch.php .../app/Jobs/Crm/Hubspot/ImportAccountBatch.php, class
ImportCallsCommand.php .../app/Console/Commands/Dev/ImportCallsCommand.php, class
ImportCallTest.php .../tests/Unit/Jobs/Activity/Import/ImportCallTest.php, final class
ImportContactBatch.php .../app/Jobs/Crm/Hubspot/ImportContactBatch.php, class
ImportBotRecordingJob.php .../app/Services/RecallAI/Jobs/ImportBotRecordingJob.php, class
ImportAccountBatchTest.php .../tests/Unit/Jobs/Crm/ImportAccountBatchTest.php, class
ImportContactBatchTest.php .../tests/Unit/Jobs/Crm/ImportContactBatchTest.php, class
ImportBotRecordingJobTest.php .../tests/Unit/Services/RecallAI/Jobs/ImportBotRecordingJobTest.php, class
ImportCall.php.html build/coverage/Jobs/Activity/Import
ImportActivityTypes.php.html build/coverage/Listeners/Crm
ImportCallsCommand.php.html build/coverage/Console/Commands/Dev
… more
Listeners/Crm/ImportActivityTypes.php
Open In Right Split...
|
45150
|
NULL
|
NULL
|
NULL
|
|
45150
|
1621
|
8
|
2026-05-14T14:22:45.653546+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768565653_m1.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% (C47•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestvProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php:8• Thu 14 May 17:22:45* :Q= custom.log› D ProvidersUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.phpD Sessionsv D Sms• DeleteCrmEntityTrait.phpDeleteAccountJob.phpImportActivityTypes.php X9 AccountController.phpE IntegrationAppTrait.php> O Intercomenv.stagingE.envDetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.phpv D PlanhatClient.php18© CreateSmsRecei© CreateSmsSentE© CreateReceivedNotC SmsListener.php> D Softphone© DialerMetricslmported.© ElasticSearchMetricsR© GenerateExportToken:© ImportRemote TrackLis© PlanhatActivityListeneReindexForAccountLisC ReindexForContactList© ReindexForGroupListelC ReindexForLeadListenReindexForOpportunit!© ReindexForUserListent© ResolveProvider.php© SendExportEmail.php© SetupintegrationActior© UserPilotActivityListen> C Authenticationv AutomatedReportsv C UserPilot|© TrackAutomatedRe> • Calendarsv D CrmBootstrapintegrationAl© ImportActivityTypes.pl© ImportMetadata.php© InitProfiles.php © HubspotPaginationService.php© HandleHubspotRateLimit.phpclass ImportActivitxTypes implementsShouldQueuepublic function handle(PlaybookCreated $event): voidTT Jon't run it somenow we atready nave categories.if ($playbook->getCategories()->isNotEmpty()) {return;A1$values = []:try {$crmService = $this->crmResolver->resolveForTeam($playbook->getTeamO):$crmService->syncField($playbook->getActivityField();$values = $crmService->importPicklistValues($playbook->getActivityField());} catch (Throwable $e) {Log::warning( message: '[ImportActivityTypes] CRM API failed, falling back to database values', ['playbook_id' => $playbook->getId),'team_id' => Splaybook->getTeamIdO.'error' => $e->getMessage(),1):if (empty($values)) {$values = $this->fetchActivityFieldValues(Splaybook->getActivityField);Log::info( message: '[ImportActivityTypes] Using database fallback for categories', l'playbook_id' => Splaybook->getId(),'field_values_count' => $values->count(),1):@ I avnitMndifierl isteneWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oi V234m teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENid FROMsocial,I on u.id= sa.:1..n<->1: on t.L_id = 1052 andIMaccounts wheiactivities49:44UTF-8Co 4 spaces...
|
NULL
|
2832691924500541138
|
NULL
|
app_switch
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% (C47•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestvProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php:8• Thu 14 May 17:22:45* :Q= custom.log› D ProvidersUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.phpD Sessionsv D Sms• DeleteCrmEntityTrait.phpDeleteAccountJob.phpImportActivityTypes.php X9 AccountController.phpE IntegrationAppTrait.php> O Intercomenv.stagingE.envDetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.phpv D PlanhatClient.php18© CreateSmsRecei© CreateSmsSentE© CreateReceivedNotC SmsListener.php> D Softphone© DialerMetricslmported.© ElasticSearchMetricsR© GenerateExportToken:© ImportRemote TrackLis© PlanhatActivityListeneReindexForAccountLisC ReindexForContactList© ReindexForGroupListelC ReindexForLeadListenReindexForOpportunit!© ReindexForUserListent© ResolveProvider.php© SendExportEmail.php© SetupintegrationActior© UserPilotActivityListen> C Authenticationv AutomatedReportsv C UserPilot|© TrackAutomatedRe> • Calendarsv D CrmBootstrapintegrationAl© ImportActivityTypes.pl© ImportMetadata.php© InitProfiles.php © HubspotPaginationService.php© HandleHubspotRateLimit.phpclass ImportActivitxTypes implementsShouldQueuepublic function handle(PlaybookCreated $event): voidTT Jon't run it somenow we atready nave categories.if ($playbook->getCategories()->isNotEmpty()) {return;A1$values = []:try {$crmService = $this->crmResolver->resolveForTeam($playbook->getTeamO):$crmService->syncField($playbook->getActivityField();$values = $crmService->importPicklistValues($playbook->getActivityField());} catch (Throwable $e) {Log::warning( message: '[ImportActivityTypes] CRM API failed, falling back to database values', ['playbook_id' => $playbook->getId),'team_id' => Splaybook->getTeamIdO.'error' => $e->getMessage(),1):if (empty($values)) {$values = $this->fetchActivityFieldValues(Splaybook->getActivityField);Log::info( message: '[ImportActivityTypes] Using database fallback for categories', l'playbook_id' => Splaybook->getId(),'field_values_count' => $values->count(),1):@ I avnitMndifierl isteneWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oi V234m teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENid FROMsocial,I on u.id= sa.:1..n<->1: on t.L_id = 1052 andIMaccounts wheiactivities49:44UTF-8Co 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45126
|
1619
|
71
|
2026-05-14T14:20:38.811878+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768438811_m1.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.054166667,"top":0.027777778,"width":0.08055556,"height":0.035555556},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.13472222,"top":0.027777778,"width":0.25555557,"height":0.035555556},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.6326389,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.6645833,"top":0.027777778,"width":0.15902779,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.82361114,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.8472222,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.87083334,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.9291667,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9527778,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9763889,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.80277777,"top":0.24333334,"width":0.015277778,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.8215278,"top":0.24111111,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.8368056,"top":0.24111111,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.85486114,"top":0.31,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.87291664,"top":0.31,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.9138889,"top":0.31,"width":0.059027776,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"bounds":{"left":0.8645833,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.8854167,"top":0.34444445,"width":0.015277778,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.9048611,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"4","depth":4,"bounds":{"left":0.92569447,"top":0.34444445,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.9458333,"top":0.3422222,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.9611111,"top":0.3422222,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","depth":4,"on_screen":true,"value":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.025,"top":0.06666667,"width":0.050694443,"height":0.034444444},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2936739681513006038
|
4956946545843311197
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
45125
|
NULL
|
NULL
|
NULL
|
|
45125
|
1619
|
70
|
2026-05-14T14:20:23.654817+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768423654_m1.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelplhl100% <7•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:20:23* :QProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php:= custom.log› D ProvidersUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php> O Sessionsv D Sms• DeleteCrmEntityTrait.phpDeleteAccountJob.phpImportActivityTypes.php X9 AccountController.phpE IntegrationAppTrait.php> O Intercom= .env.stagingE.envDetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.phpv D PlanhatClient.php18© CreateSmsRecei© CreateSmsSentE19© CreateReceivedNot35C SmsListener.php44© HubspotPaginationService.phpHandleHubspotRateLimit.phpclass ImportActivitxTypes implementsShouldQueuepublic function handle(PlaybookCreated $event): void$values = 0J:A1> D Softphone45© DialerMetricslmported.46© ElasticSearchMetricsR47© GenerateExportToken:48© ImportRemote TrackLis49© PlanhatActivityListene50ReindexForAccountLis51C ReindexForContactList52© ReindexForGroupListel53C ReindexForLeadListen54try {$crmService = $this->crmResolver->resolveForTeam(Splaybook->getTeamO):$crmService->syncField($playbook->getActivityField();$values = $crmService->importPicklistValues($playbook->getActivityFieldO);} catch (Throwable $e) {Log::warning( message:'[ImportActivityTypes] CRM API failed, falling back to database values','playbook_id' = $playbook->getId(),'team_id'=> $playbook->getTeamId,'error' => $e-›getMessage(),ReindexForOpportunit!551);© ReindexForUserListent56© ResolveProvider.php57© SendExportEmail.php58© SetupintegrationActior59if (empty($values)) {$values = $this->fetchActivityFieldValues($playbook->getActivityField));© UserPilotActivityListen60> C Authentication61v AutomatedReports62v C UserPilot|63Log::info( message:'[ImportActivityTypes] Using database fallback for categories', ['playbook_id' => $playbook->getId(),'field_values_count' => $values->count(),© TrackAutomatedRe641):> • Calendars65}-v D Crm66BootstrapintegrationAl67$createdCount = 0;© ImportActivityTypes.pl68© ImportMetadata.php69/** @var stdClass{label:string} $value */© InitProfiles.php70foreach (Svalues as $value) 1@ I avnitMndifiarl istene71$dataWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oi V234m teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial.1 on u.id= sa.:1..n<->1: on t.Lid = 1052 andIMaccounts wheiactivities49:44UTF-8Co 4 spaces...
|
NULL
|
-9004147329109048839
|
NULL
|
visual_change
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelplhl100% <7•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest8• Thu 14 May 17:20:23* :QProject v© ReportController.php© AutomatedReportGenerated.phpTrackAutomatedReportGeneratedEvent.phpPlaybackController.php:= custom.log› D ProvidersUserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.phpSendReportJob.php> O Sessionsv D Sms• DeleteCrmEntityTrait.phpDeleteAccountJob.phpImportActivityTypes.php X9 AccountController.phpE IntegrationAppTrait.php> O Intercom= .env.stagingE.envDetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© MatchActivityCrmData.phpv D PlanhatClient.php18© CreateSmsRecei© CreateSmsSentE19© CreateReceivedNot35C SmsListener.php44© HubspotPaginationService.phpHandleHubspotRateLimit.phpclass ImportActivitxTypes implementsShouldQueuepublic function handle(PlaybookCreated $event): void$values = 0J:A1> D Softphone45© DialerMetricslmported.46© ElasticSearchMetricsR47© GenerateExportToken:48© ImportRemote TrackLis49© PlanhatActivityListene50ReindexForAccountLis51C ReindexForContactList52© ReindexForGroupListel53C ReindexForLeadListen54try {$crmService = $this->crmResolver->resolveForTeam(Splaybook->getTeamO):$crmService->syncField($playbook->getActivityField();$values = $crmService->importPicklistValues($playbook->getActivityFieldO);} catch (Throwable $e) {Log::warning( message:'[ImportActivityTypes] CRM API failed, falling back to database values','playbook_id' = $playbook->getId(),'team_id'=> $playbook->getTeamId,'error' => $e-›getMessage(),ReindexForOpportunit!551);© ReindexForUserListent56© ResolveProvider.php57© SendExportEmail.php58© SetupintegrationActior59if (empty($values)) {$values = $this->fetchActivityFieldValues($playbook->getActivityField));© UserPilotActivityListen60> C Authentication61v AutomatedReports62v C UserPilot|63Log::info( message:'[ImportActivityTypes] Using database fallback for categories', ['playbook_id' => $playbook->getId(),'field_values_count' => $values->count(),© TrackAutomatedRe641):> • Calendars65}-v D Crm66BootstrapintegrationAl67$createdCount = 0;© ImportActivityTypes.pl68© ImportMetadata.php69/** @var stdClass{label:string} $value */© InitProfiles.php70foreach (Svalues as $value) 1@ I avnitMndifiarl istene71$dataWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams=laravel.logSF [jiminny@localhost]A HS_local [jiminny@localho:W4 console [QAI PROD] X4 console [PROD]A console (EU]Go jiminny0841A3 X4 A Vm migrations oi V234m teams wherem crm_layouts !iM crm_layout_eiIM crm_fields Wim features;m team_feature:m opportunitie:m teams;1.id, CASEWHENidFROMsocial.1 on u.id= sa.:1..n<->1: on t.Lid = 1052 andIMaccounts wheiactivities49:44UTF-8Co 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45124
|
1620
|
47
|
2026-05-14T14:20:21.469069+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768421469_m2.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIđ 0Pm~ (Q SearchDate ModifiedYesterdav at 13.34Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:32Yesterday at 13:31Yesterdav at 13:30Yesterday at 13:30Yesterday at 13.29Yesterday at 13:28resterday at 15.21Yesterdav at 13:27Yesterday at 13:26Yesterday at 13:26Yesterday at 13:23Yesterday at 13:25Yesterday at 13.24Yesterdav at 13:23Yesterday at 13:22Yesterday at 13:21Yesterday at 13:20Yesterday at 13.19Yesterdav at 13:19Yesterday at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.16Yecterdav at 12:15Yesterday at 13:15Yesterday at 13-14Yesterdav at 13:14Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:12Yesterday at 13.11Yesterdav at 13:10Yesterday at 13:10Yesterday at 13:09Yoctorday at 12:09Yesterday at 13:08Yesterday at 13.0Yecterdav at 12:07Yesterday at 13:06Yesterdav at 13:0529 K:MPEG-4 movie6 KBMPEG-4 movie12 KBMPEG-4 movieMPEG-4 movie7 KBI8 KB37 KBMPEG-4 movie10 K:7 KBMPEG-4 movie8 KBMPEG-4 movie8 KBMPEG-4 movie72 KB14 KBMPEG-4 movie13 KE9KBMPEG-4 movie18 KB12 KB|10 KRIMPEG-4 movieMPEG-4 movie16 KB6 KBMPEG-4 movie6KEMPEG-4 movie12 KBMPEG-4 movie23 KB8 K:MPEG-4 movie6 KBMPEG-4 movie6 KB11 KBMPEG-4 movie11 KEMPEG-4 movie20 KBMPEG-4 movie34 KB10 K:MPEG-4 movie7 KBMPEG-4 movie5 KB11 KBMPEG-4 movie26KPMPEG-4 movie111 KB MPEG-4 movie102 KB88 KBMPEG-4 movie59 KBMPEG-4 movie98 KB97 KBRAKRMPEG-4 movieMDEG-A movie44 KB93 KBMPEG-4 movie78 K:MPEG-A movid50 KBMPEG-4 movie58 KB27 KB7 KPMPEG-4 movieMPEG-4 movie12 KB32 KBMPEG-4 movie17 Kг19 KBMPEG-4 movie32 KB10KBMPEG-4 movieAl Notes: OffLeave• 0FavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network_• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-yWJo.zioPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dmaimage.jpg- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfKoválik Family Tree.gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pa• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.64 GB availabld• Inu 14 May 1/-20-20Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
-7232422226861611523
|
NULL
|
click
|
ocr
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIđ 0Pm~ (Q SearchDate ModifiedYesterdav at 13.34Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:32Yesterday at 13:31Yesterdav at 13:30Yesterday at 13:30Yesterday at 13.29Yesterday at 13:28resterday at 15.21Yesterdav at 13:27Yesterday at 13:26Yesterday at 13:26Yesterday at 13:23Yesterday at 13:25Yesterday at 13.24Yesterdav at 13:23Yesterday at 13:22Yesterday at 13:21Yesterday at 13:20Yesterday at 13.19Yesterdav at 13:19Yesterday at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.16Yecterdav at 12:15Yesterday at 13:15Yesterday at 13-14Yesterdav at 13:14Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:12Yesterday at 13.11Yesterdav at 13:10Yesterday at 13:10Yesterday at 13:09Yoctorday at 12:09Yesterday at 13:08Yesterday at 13.0Yecterdav at 12:07Yesterday at 13:06Yesterdav at 13:0529 K:MPEG-4 movie6 KBMPEG-4 movie12 KBMPEG-4 movieMPEG-4 movie7 KBI8 KB37 KBMPEG-4 movie10 K:7 KBMPEG-4 movie8 KBMPEG-4 movie8 KBMPEG-4 movie72 KB14 KBMPEG-4 movie13 KE9KBMPEG-4 movie18 KB12 KB|10 KRIMPEG-4 movieMPEG-4 movie16 KB6 KBMPEG-4 movie6KEMPEG-4 movie12 KBMPEG-4 movie23 KB8 K:MPEG-4 movie6 KBMPEG-4 movie6 KB11 KBMPEG-4 movie11 KEMPEG-4 movie20 KBMPEG-4 movie34 KB10 K:MPEG-4 movie7 KBMPEG-4 movie5 KB11 KBMPEG-4 movie26KPMPEG-4 movie111 KB MPEG-4 movie102 KB88 KBMPEG-4 movie59 KBMPEG-4 movie98 KB97 KBRAKRMPEG-4 movieMDEG-A movie44 KB93 KBMPEG-4 movie78 K:MPEG-A movid50 KBMPEG-4 movie58 KB27 KB7 KPMPEG-4 movieMPEG-4 movie12 KB32 KBMPEG-4 movie17 Kг19 KBMPEG-4 movie32 KB10KBMPEG-4 movieAl Notes: OffLeave• 0FavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network_• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-yWJo.zioPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dmaimage.jpg- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfKoválik Family Tree.gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pa• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.64 GB availabld• Inu 14 May 1/-20-20Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
45122
|
NULL
|
NULL
|
NULL
|
|
45123
|
1619
|
69
|
2026-05-14T14:20:21.470404+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768421470_m1.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelplhl•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestProject v100% C8• Thu 14 May 17:20:21Q© ReportController.php© AutomatedReportGenerated.php= custom.log= laravel.log› D Providers© TrackAutomatedReportGeneratedEvent.phpPlaybackController.php4 SF (jiminny@localhost]HS_local (jiminny@localhost)D Sessionsv D Sms.© UserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php4 console [QAI PROD] X« console [PROD]> O IntercomSendReportJob.php• DeleteCrmEntityTrait.php© DeleteAccountJob.php« console [EU]v D Planhat© ImportActivityTypes.php X© AccountController.php• IntegrationAppTrait.php.env.stagingD18Tx: Auto vd8 jiminny© CreateSmsRecei© CreateSmsSentEE.env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php21008 41 A3 44 A V© CreateReceivedNot211m migrations order by id desc;C SmsListener.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.php212> D Softphone© HandleHubspotRateLimit.php213m teams where id IN (1, 1037);© DialerMetricslmported.19class ImportActivitylypes implementsShouldQueueA1 ^214m crm_layouts where crm_configuration_id = 1© ElasticSearchMetricsR35public function handle(PlaybookCreated $event): void215M crm_layout_entities WHERE crm_layout_id =© GenerateExportToken:44Svalues = 0:216M crm_fields WHERE id IN (1652,1661,66799,66© ImportRemote TrackLis45217© PlanhatActivityListene46try {218m features;ReindexForAccountLis47$crmService = Sthis->crmResolver->resolveForTeam(Splaybook->getTeam());219m team_features where feature_id = 33;C ReindexForContactList48$crmService->syncField($playbook->getActivityFieldO);220m opportunities;© ReindexForGroupListel49$values = $crmService->importPicklistValues($playbook->getActivityFieldC:221C ReindexForLeadListen50} catch (Throwable $e) {222m teams;ReindexForOpportunit!51Log: :warning( message:'[ImportActivityTypes] CRM API failed, falling back 223© ReindexForUserListent52'playbook_id' = $playbook->getId,224..id, CASE WHEN u.id = t.owner_id THEN ' (own© ResolveProvider.php53'team_id' => $playbook->getTeamId),225© SendExportEmail.php54'error' => $e->getMessage).226© SetupintegrationActior551):227id FROM social_accounts sa© UserPilotActivityListen22856on u.id = sa.sociable_id> C Authentication229571..n<->1: on t.id = u.team_idv AutomatedReports58if (empty(Svalues)) {230Lid = 1052 and sa.provider = 'hubspot':v C UserPilot|59$values = $this->fetchActivityFieldValues($playbook->getActivityField()) :231© TrackAutomatedRe23260accounts where id = 11512582;• Calendars61Log:: info( message:'[ImportActivityTypes] Using database fallback forcat 233 vactivities where account_id = 11512582;D Crm62'playbook_id' => $playbook->getId),234BootstrapintegrationAl63'field_values_count' => $values->count(),© ImportActivityTypes.pl641):© ImportMetadata.php65© InitProfiles.php66@ I avnitMndifierl istene67ScreatedfnuntWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams49:44UTF-8Co 4 spaces...
|
NULL
|
791029799661590128
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelplhl•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTestProject v100% C8• Thu 14 May 17:20:21Q© ReportController.php© AutomatedReportGenerated.php= custom.log= laravel.log› D Providers© TrackAutomatedReportGeneratedEvent.phpPlaybackController.php4 SF (jiminny@localhost]HS_local (jiminny@localhost)D Sessionsv D Sms.© UserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php4 console [QAI PROD] X« console [PROD]> O IntercomSendReportJob.php• DeleteCrmEntityTrait.php© DeleteAccountJob.php« console [EU]v D Planhat© ImportActivityTypes.php X© AccountController.php• IntegrationAppTrait.php.env.stagingD18Tx: Auto vd8 jiminny© CreateSmsRecei© CreateSmsSentEE.env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php21008 41 A3 44 A V© CreateReceivedNot211m migrations order by id desc;C SmsListener.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.php212> D Softphone© HandleHubspotRateLimit.php213m teams where id IN (1, 1037);© DialerMetricslmported.19class ImportActivitylypes implementsShouldQueueA1 ^214m crm_layouts where crm_configuration_id = 1© ElasticSearchMetricsR35public function handle(PlaybookCreated $event): void215M crm_layout_entities WHERE crm_layout_id =© GenerateExportToken:44Svalues = 0:216M crm_fields WHERE id IN (1652,1661,66799,66© ImportRemote TrackLis45217© PlanhatActivityListene46try {218m features;ReindexForAccountLis47$crmService = Sthis->crmResolver->resolveForTeam(Splaybook->getTeam());219m team_features where feature_id = 33;C ReindexForContactList48$crmService->syncField($playbook->getActivityFieldO);220m opportunities;© ReindexForGroupListel49$values = $crmService->importPicklistValues($playbook->getActivityFieldC:221C ReindexForLeadListen50} catch (Throwable $e) {222m teams;ReindexForOpportunit!51Log: :warning( message:'[ImportActivityTypes] CRM API failed, falling back 223© ReindexForUserListent52'playbook_id' = $playbook->getId,224..id, CASE WHEN u.id = t.owner_id THEN ' (own© ResolveProvider.php53'team_id' => $playbook->getTeamId),225© SendExportEmail.php54'error' => $e->getMessage).226© SetupintegrationActior551):227id FROM social_accounts sa© UserPilotActivityListen22856on u.id = sa.sociable_id> C Authentication229571..n<->1: on t.id = u.team_idv AutomatedReports58if (empty(Svalues)) {230Lid = 1052 and sa.provider = 'hubspot':v C UserPilot|59$values = $this->fetchActivityFieldValues($playbook->getActivityField()) :231© TrackAutomatedRe23260accounts where id = 11512582;• Calendars61Log:: info( message:'[ImportActivityTypes] Using database fallback forcat 233 vactivities where account_id = 11512582;D Crm62'playbook_id' => $playbook->getId),234BootstrapintegrationAl63'field_values_count' => $values->count(),© ImportActivityTypes.pl641):© ImportMetadata.php65© InitProfiles.php66@ I avnitMndifierl istene67ScreatedfnuntWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)W Windsurf Teams49:44UTF-8Co 4 spaces...
|
45121
|
NULL
|
NULL
|
NULL
|
|
45122
|
1620
|
46
|
2026-05-14T14:20:16.211269+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768416211_m2.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterdav at 13.33Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:31Yesterday at 13:30Yesterdav at 13:30Yesterday at 13:29Yesterday at 13.28Yesterday at 13:28resterday at 15.21Yesterdav at 13:26Yesterday at 13:26Yesterday at 13:25Yesterday at 13:23Yesterday at 13:24resterday at 13-43Yesterdav at 13:22Testerady dl ls.2.Yesterday at 13:20Yesterday at 13:20Yesterday at 13.19Yesterdav at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.15Yecterdav at 12:15Yesterday at 13:14Yesterday at 13-14Yesterdav at 13:13Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:11Yesterday at 13:10Yesterdav at 13:10Yesterday at 13:09Yesterday at 13:08Yoctorday at 12:09Yesterday at 13.0/Yocterdav at 13:06Yesterday at 13:06Yesterdav at 13:05MPEG-4 movie12 KBMPEG-4 movie9 KBMPEG-4 movieMPEG-4 movie8 KE37 KB10 KBMPE0"4 movie7 K:8 KBMPEG-4 movie9 KBMPEG-4 movie72 KBMPEG-4 movie14 KB13 KBMPEG-4 movie9 K:18 KBMPEG-4 movie12 KB10 K:16 KRIMPEG-4 movieMPEG-4 movie6 KBMPEG-4 movie12 KE23 KBMPEG-4 movie8 KB6 KB1MPEG-4 movie6 KBMPEG-4 movie11 KB11 KBMPEG-4 movie20 KEMPEG-4 movie34 KBMPEG-4 movie10 KB7K:MPEG-4 movie5 KBMPEG-4 movie11 KB26 KBMPEG-4 movie111 KPMPEG-4 movie102 KBMPEG-4 movie88 KB59 K:MPEG-4 movie98 KBMPEG-4 movie97 KB66 KBЛAKEMPEG-4 movieMDEG-A movie93 KB78 KBMPEG-4 movie50 K:MPEG-A movid58 KB MPEG-4 movie27 KB7 KB112 KрMPEG-4 movieMPEG-4 movie32 KB17 KBMPEG-4 movie19 Kг32 KBMPEG-4 movie10 KB24 K8MPEG-4 movieFavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-ywJo.ziPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dma- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence bettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.64 GB availabld• Inu 14 May 1/.20.12Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
8424883885309822950
|
NULL
|
click
|
ocr
|
NULL
|
ActivityFilesLaterJiminny... ~@ jiminny-x-integrat ActivityFilesLaterJiminny... ~@ jiminny-x-integrati& platform-inner-team© Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity_lab# engineering# general# jiminny-bg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the people of iimi..• Direct messages8. A...• A3 62P. Galya Dimitrova Mvasil VasilevA. Stefka Stoyanova%: Todor Stamatovf. Mario GeorgievP. Nikolay Ivanov2o James Graham "2. Stoyan Tanev. Steliyan Georgiev. Petko Kashinski*. Lukas Kovali...a: Apps® ToastS lira Gloud6 Huddle with Aneliya Angelova& R. Aneliya Angelova •• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някьде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova @ 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preview insackt[HubSpot] Optimise CRM rematctC OpenReady for QA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira+ SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle LIVE 4:06 PMAneliva Angelova is here toolAneliya Angelova 4:44 PM11512582Lukas Kovalik O 5:16 PMcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-Type: application/json'\--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIґ7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeave~ (Q SearchDate ModifiedYesterdav at 13.33Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:31Yesterday at 13:30Yesterdav at 13:30Yesterday at 13:29Yesterday at 13.28Yesterday at 13:28resterday at 15.21Yesterdav at 13:26Yesterday at 13:26Yesterday at 13:25Yesterday at 13:23Yesterday at 13:24resterday at 13-43Yesterdav at 13:22Testerady dl ls.2.Yesterday at 13:20Yesterday at 13:20Yesterday at 13.19Yesterdav at 13:18Yesterday at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.15Yecterdav at 12:15Yesterday at 13:14Yesterday at 13-14Yesterdav at 13:13Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:11Yesterday at 13:10Yesterdav at 13:10Yesterday at 13:09Yesterday at 13:08Yoctorday at 12:09Yesterday at 13.0/Yocterdav at 13:06Yesterday at 13:06Yesterdav at 13:05MPEG-4 movie12 KBMPEG-4 movie9 KBMPEG-4 movieMPEG-4 movie8 KE37 KB10 KBMPE0"4 movie7 K:8 KBMPEG-4 movie9 KBMPEG-4 movie72 KBMPEG-4 movie14 KB13 KBMPEG-4 movie9 K:18 KBMPEG-4 movie12 KB10 K:16 KRIMPEG-4 movieMPEG-4 movie6 KBMPEG-4 movie12 KE23 KBMPEG-4 movie8 KB6 KB1MPEG-4 movie6 KBMPEG-4 movie11 KB11 KBMPEG-4 movie20 KEMPEG-4 movie34 KBMPEG-4 movie10 KB7K:MPEG-4 movie5 KBMPEG-4 movie11 KB26 KBMPEG-4 movie111 KPMPEG-4 movie102 KBMPEG-4 movie88 KB59 K:MPEG-4 movie98 KBMPEG-4 movie97 KB66 KBЛAKEMPEG-4 movieMDEG-A movie93 KB78 KBMPEG-4 movie50 K:MPEG-A movid58 KB MPEG-4 movie27 KB7 KB112 KрMPEG-4 movieMPEG-4 movie32 KB17 KBMPEG-4 movie19 Kг32 KBMPEG-4 movie10 KB24 K8MPEG-4 movieFavouritesE jiminny© Recents* ApplicationsiCloudiCloud Drive228 Sync folderQ DXP4800PLUS-B5FA@ Network|• CRMI• Orange• Red• Yellow• Green• Purple•) All lags..lohlDownloadsNameLoom.pkgAlfred copv.alfredoreterencesB KeychronAssist-1.0.2 (1).dmgA Keychron Assist-1.0.2.dmgmazanoke-images-ywJo.ziPhotos-3-001.zipD Transcript.pdf→mage U.loge1 Orioninstaller.dma- image (2).1pc• ПО-22221726037035-004-001_ORGES.pdf• %D0%9F%D0%9E-22221726037035-004-001_archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterences05012026_0000000026574472_ SWIFT_OB70501260015890.pdf27022026_0000000026574472_SWIFT_OB72702260049200.pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001B reporti) xm=pdt.odipdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfB Rovaix Famly Treo gedbitwarden export 20251031122528.isonKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst_aid_notes_complete.docxrenortl2).esvconfig.ymlIteration run Search HS.postman_collection.json--report(1).csvm licence bettertouchtoalMariusHosting Config.json1ooks-891a6503-bbb7-4b2b-9c3.csv•Alfredmazanoke-images-YWJ6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик.jpg• Dhotac 2.001Q SearchKind00,4 MDinstdlle..dckage55.9 MBAlfred...ferences10,1 MBDisk Image10,1 MBDisk ImageIL MBLiP archive6,6 MBZIP archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDF Document140 KbZIP archive148 KВZIP archivel148 KBZIP archive122 KBXML document111 KBAlfred...ferences94 KBPDF Document92 KBPDr DocumentK:91 KB91 KB30 KB29 KBPDF DocumentXML documentPDF Document28 KBPDF Document28 KR28 KB27 KB14 KB11 KB6 KB6KBPDE DocumentDocumentJSONICSV DocumentZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBYAML document1 KBcSV Document928 byteshttlicence183 bytesZero butesJSONAlfred.. ferencesZero bytesFolde1,9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.64 GB availabld• Inu 14 May 1/.20.12Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3713 Feb 2026 at 11:54Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nov 2025 at 17:596 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0418 Mar 2026 at 11:5510 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:3630 Jan 2026 at 12:3616 Oct 2025 aт 16:0123 Apr 2026 at 13:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45121
|
1619
|
68
|
2026-05-14T14:20:19.077622+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768419077_m1.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.054166667,"top":0.027777778,"width":0.08055556,"height":0.035555556},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.13472222,"top":0.027777778,"width":0.25555557,"height":0.035555556},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.6326389,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.6645833,"top":0.027777778,"width":0.15902779,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.82361114,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.8472222,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.87083334,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.9291667,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9527778,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9763889,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.64166665,"top":0.34666666,"width":0.015277778,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.66041666,"top":0.34444445,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.67569447,"top":0.34444445,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.69375,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.7118056,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.7347222,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.75277776,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.7708333,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.79375,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.81666666,"top":0.20666666,"width":0.050694443,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.87222224,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.9138889,"top":0.20666666,"width":0.059027776,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"bounds":{"left":0.8645833,"top":0.24111111,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.8854167,"top":0.24111111,"width":0.015277778,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.9048611,"top":0.24111111,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"4","depth":4,"bounds":{"left":0.92569447,"top":0.24111111,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.9458333,"top":0.23888889,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.9611111,"top":0.23888889,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","depth":4,"on_screen":true,"value":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.025,"top":0.06666667,"width":0.050694443,"height":0.034444444},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2936739681513006038
|
4956946545843311197
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45120
|
1619
|
67
|
2026-05-14T14:20:16.213684+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768416213_m1.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelp•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vProject v© ReportController.php© AutomatedReportGenerated.phplhlHandleHubspotRateLimitTest100% C8• Thu 14 May 17:20:15Q= custom.log= laravel.log› D Providers© TrackAutomatedReportGeneratedEvent.phpPlaybackController.phpD Sessionsv D Sms© UserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php> O IntercomSendReportJob.php• DeleteCrmEntityTrait.phpDeleteAccountJob.phpv D Planhat© ImportActivityTypes.php X© AccountController.php• IntegrationAppTrait.php=.env.stagingD18© CreateSmsRecei© CreateSmsSentEE.env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php210© CreateReceivedNot211C SmsListener.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.php212> D Softphone© HandleHubspotRateLimit.php213© DialerMetricslmported.19class ImportActivitylypes implementsShouldQueueA1 л214© ElasticSearchMetricsR35public function handle(PlaybookCreated $event): void21536© GenerateExportToken:1/10 >© ImportRemote TrackLis37$playbook = $event->playbook;© Service© PlanhatActivityListene38ReindexForAccountLis39// Don't run if somehow we already havpublic function importPicklistValues(C ReindexForContactList40if ($playbook->getCategories()->isNotEField $field): array© ReindexForGroupListel41return;42C ReindexForLeadListenImplements: SyncCrmEntitiesInterface::43ReindexForOpportunit!importPicklistValues44© ReindexForUserListene$values = [];© ResolveProvider.php45Parameters:\Field$field46© SendExportEmail.phptry {Source:.../app/Services/Crm/Close/© SetupintegrationActior47$crmService = $this->crmResolver->Service.php48© UserPilotActivityListen$crmService->syncField(Splaybook->> C Authentication49$values = $crmService->importPicklistValues($playbook->getActivityFi‹22950v AutomatedReports} catch (Throwable $e) {230v C UserPilot|51Log: :warning( message:'[ImportActivityTypes] CRM API failed, falling 231© TrackAutomatedRe52'playbook_id' = $playbook->getid,232Calendars53'team_id' => $playbook->getTeamId(),233 /D Crm54'error' => $e-›getMessage,23455BootstrapintegrationAl1):© ImportActivityTypes.pl56© ImportMetadata.php57© InitProfiles.php58if (empty($values)) {@ I avnitMndifierl istene59$values = $this->fetchActivityFieldValues($playbook->getActivityFielWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)4 SF (jiminny@localhost]HS_local (jiminny@localhost)4 console [QAI PROD] X« console [PROD]« console [EU]Tx: Auto vdo jiminny08 41 A3 44 A Vm migrations order by id desc;m teams where id IN (1, 1037);m crm_layouts where crm_configuration_id = 1M crm_layout_entities WHERE crm_layout_id =crm_fields WHERE id IN (1652,1661,66799,66features;team_features where feature_id = 33;opportunities;teams;id, CASE WHEN u.id = t.owner_id THEN ' (ownd FROM social_accounts saon u.id = sa.sociable_id1..n<->1: on t.id = u.team_idLid = 1052 and sa.provider = 'hubspot':accounts where id = 11512582;activities where account_id = 11512582;W Windsurf Teams49:47UTF-8Co 4 spaces...
|
NULL
|
-1560646643682456371
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelp•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vProject v© ReportController.php© AutomatedReportGenerated.phplhlHandleHubspotRateLimitTest100% C8• Thu 14 May 17:20:15Q= custom.log= laravel.log› D Providers© TrackAutomatedReportGeneratedEvent.phpPlaybackController.phpD Sessionsv D Sms© UserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php> O IntercomSendReportJob.php• DeleteCrmEntityTrait.phpDeleteAccountJob.phpv D Planhat© ImportActivityTypes.php X© AccountController.php• IntegrationAppTrait.php=.env.stagingD18© CreateSmsRecei© CreateSmsSentEE.env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php210© CreateReceivedNot211C SmsListener.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.php212> D Softphone© HandleHubspotRateLimit.php213© DialerMetricslmported.19class ImportActivitylypes implementsShouldQueueA1 л214© ElasticSearchMetricsR35public function handle(PlaybookCreated $event): void21536© GenerateExportToken:1/10 >© ImportRemote TrackLis37$playbook = $event->playbook;© Service© PlanhatActivityListene38ReindexForAccountLis39// Don't run if somehow we already havpublic function importPicklistValues(C ReindexForContactList40if ($playbook->getCategories()->isNotEField $field): array© ReindexForGroupListel41return;42C ReindexForLeadListenImplements: SyncCrmEntitiesInterface::43ReindexForOpportunit!importPicklistValues44© ReindexForUserListene$values = [];© ResolveProvider.php45Parameters:\Field$field46© SendExportEmail.phptry {Source:.../app/Services/Crm/Close/© SetupintegrationActior47$crmService = $this->crmResolver->Service.php48© UserPilotActivityListen$crmService->syncField(Splaybook->> C Authentication49$values = $crmService->importPicklistValues($playbook->getActivityFi‹22950v AutomatedReports} catch (Throwable $e) {230v C UserPilot|51Log: :warning( message:'[ImportActivityTypes] CRM API failed, falling 231© TrackAutomatedRe52'playbook_id' = $playbook->getid,232Calendars53'team_id' => $playbook->getTeamId(),233 /D Crm54'error' => $e-›getMessage,23455BootstrapintegrationAl1):© ImportActivityTypes.pl56© ImportMetadata.php57© InitProfiles.php58if (empty($values)) {@ I avnitMndifierl istene59$values = $this->fetchActivityFieldValues($playbook->getActivityFielWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)4 SF (jiminny@localhost]HS_local (jiminny@localhost)4 console [QAI PROD] X« console [PROD]« console [EU]Tx: Auto vdo jiminny08 41 A3 44 A Vm migrations order by id desc;m teams where id IN (1, 1037);m crm_layouts where crm_configuration_id = 1M crm_layout_entities WHERE crm_layout_id =crm_fields WHERE id IN (1652,1661,66799,66features;team_features where feature_id = 33;opportunities;teams;id, CASE WHEN u.id = t.owner_id THEN ' (ownd FROM social_accounts saon u.id = sa.sociable_id1..n<->1: on t.id = u.team_idLid = 1052 and sa.provider = 'hubspot':accounts where id = 11512582;activities where account_id = 11512582;W Windsurf Teams49:47UTF-8Co 4 spaces...
|
45118
|
NULL
|
NULL
|
NULL
|
|
45119
|
1620
|
45
|
2026-05-14T14:20:02.379621+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768402379_m2.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Jiminny... ~ActivityFilesLater@ jiminny-x-integrat Jiminny... ~ActivityFilesLater@ jiminny-x-integrati• plattorm-inner-teamE Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity lab# engineering# general#jiminny-bgac nlattorm-nckets# product launches# random# releases# sofia-officed sunport# thank-yous# the people of iimi... Direct messages• 8la 62% Galya Dimitrovavasil VasilevM Stefka StovanovaSg: Todor StamatovMario GeorgievNiudlay lanay. James Graham "* Stoyan Tanevo Stelivan Georgiev( Petko Kashinski*. Lukas Kovali...::: AnnsToastS lira Gloud6d Huddle with Aneliva Angelova* Aneliya Angelova &• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някъде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preuiew in sact[HubSpotl Optimise CRM rematct(7 OpenRosdy for OA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira* SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle (LIVE 4:06 PMAneliva Angelova is here toolAneliva Angelova 4:44 PN11512582Lukas Kovalik M 5.16 PNcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-vne' annlication/ison'--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIr7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeavev Q SearchDate ModifiedYesterdav at 13.33Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:31Yesterday at 13:30Yesterdav at 13:30Yesterday at 13:29Yesterday at 13.28Yesterdav at 13:28resterday at 15.21Yesterdav at 13:26Yesterday at 13:26Yesterday at 13:2:Yesterday at 13:23Yesterdav at 13:24resterday at 13-43Yesterdav at 13:22Yesterday at 13:20Voctordau at 12:20lYesterday at 13.19Yesterdav at 13:18Yesterdav at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.15Yecterdav at 12:15Yesterdav at 13:14Yesterday at 13-14Yesterdav at 13:13Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:11Yesterday at 13:10Yesterdav at 13:10Yesterday at 13:09Yesterday at 13:08Yoctorday at 12:09Yesterday at 13.0/Yocterdav at 13:06Yesterday at 13:06Yesterdav at 13:05MPEG-4 movie12 KB9 KBMDEG-A movieMPEG-4 movieMPEG-4 movie8 KE37 KB10 KBMPEG-4 movie7 K:8 KBMDEG-A movie9 KBMPEG-4 movie72 KB14 KB15 Kb9 K:MPEG-4 movieMPEG-4 movie18 KBMDECA mavio12 KE10 K:MPEG-4 movie16 KRI6 KBMPEG-A movidMPEG-4 movie12 KE23 KB8 KBMPEG-4 movie6 KB1MPEG-4 movieMDSGLA movic11 KB11 KBMPEG-4 movie20 KE34 KBMPEG-4 movieMPEG-4 movie10 KB7K:MPEG-4 movieMDEG.A movid11 KB26 KBMPEG-4 movie111 KPMDEG-A movie102 KBMPEG-4 movie88 KB59 K:98 KB97 KB66 KBMPEG-4 movieMDEC.A moviaMPEG-4 movieЛAKE93 KB78 KBMDEG-A movieMPEG-4 movie50 K:MPEG-A movid58 KB MPEG-4 movie27 KB7 KB112 KрMPEG-4 movieMDSG.A movio32 KB17 KBMPEG-4 movie19 Kг32 KBMDECA movid10 KB24 K8MPEG-4 movieFavourites• jiminny• Recents* ApplicationsiCloud• iCloud Drive992 Svnc tolde0 DXP4800PLUS-B5F49 Networl• CRMI• Orange• Red|• Yellow• Green• Purple•) All lags..IhlDownloadsNameLoom.pkgAlfred copv.alfredoreterences=KeychronAssist-1.0.2 (1).dmeKeychronAssist-1.0.2.dmgmazanoke-images-yWJo.zioPhotos-3-001.zip• Transcript.pd→mage U.loge1 Orioninstaller.dma- image (2).1pc• ПO-22221726037035-004-001_ORGES.pdf%D0%9F%D0%9E-22221726037035-004-001 archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterencesСE 060209С О000000026571172 CWICT 0Р70501260015900 ndt= 27022026_0000000026574472_ SWIFT_ [IBAN].pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001reportxmmi=pdt.odiB pdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfP Kdf-a,k Ffmiv Tree.sebitwarden export 20251031122528.isonlKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst aid_notes_complete.docxrenortl2).esviconfig.vmlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.isonnokc.901a6502.6667.A62h-062 ccu•Alfredv P1 mazanoko imaaoc. VWI6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик iро• Dhotac 2.001Q SearchKind00,4 MD55.9 MBinstdlle..dckageAlfred...ferences10,1 MB10,1 MBIL MBDisk ImageDisk ImageLiP archive6.6 MBZIp archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDE Document140 KbZIP archive148 KВ148 KB122 KBZIP archivelZIP archiveXML document111 KBAlfred...ferences94 KBDDE Documont92 KBPDr DocumentK:PDF Document91 KB91 KBXML document30 KBn0kpDDE Nocumont28 KBPDF Document28 KRPDE Document28 KB27 KBDocument14 KB11 KB6 KB6KBJSONINCV NacumontZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBVAMI dosumon1 KB029 buteccSV Documenthttlicence183 bytesZero butesJSONAlfrod foronso!Zero bytesFolde1.9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.65 GB availabld• Inu 14 May 1/.20:04Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 ,Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3712 Goh 2006 9t 11:5 A1Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nau 2025 4+ 17:506 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0419 Mar 2026 at 11:55|10 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:362616 Oct 2025 aт 16:0122 Aar 2026 at 12:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
NULL
|
-2902161996689106150
|
NULL
|
click
|
ocr
|
NULL
|
Jiminny... ~ActivityFilesLater@ jiminny-x-integrat Jiminny... ~ActivityFilesLater@ jiminny-x-integrati• plattorm-inner-teamE Channels# ai-chapter# alertsi backend# bugscontusion-cllnia# curiosity lab# engineering# general#jiminny-bgac nlattorm-nckets# product launches# random# releases# sofia-officed sunport# thank-yous# the people of iimi... Direct messages• 8la 62% Galya Dimitrovavasil VasilevM Stefka StovanovaSg: Todor StamatovMario GeorgievNiudlay lanay. James Graham "* Stoyan Tanevo Stelivan Georgiev( Petko Kashinski*. Lukas Kovali...::: AnnsToastS lira Gloud6d Huddle with Aneliva Angelova* Aneliya Angelova &• Messagest Add canvasur FilesAneliya Angelova 2:30 PMЛукаш, само при Сейлсфорс и Хубспот се синкваха активити типовете, когато се направи плейбук,нали?пои останалите скМі тоябва оъчно ла се въвелат.Lukas Kovalik 2:47 PMтряова да се за всички, някъде не се ли попьлвапри зохо май беше hardcoded но май и там си връщаха две категорииAneliya Angelova 4:00 PMЛукаш имаш ли време да се чуем за тестването на https://jiminny.atlassian.net/browse/JY-20725X Preuiew in sact[HubSpotl Optimise CRM rematct(7 OpenRosdy for OA- MediumAA Aneliya AngelovaAs of today at 4:00 PM RetreshOpen in Jira* SummariseLukas Kovalik 4:02 PMzean-iurwiniareelYou joined the huddle (LIVE 4:06 PMAneliva Angelova is here toolAneliva Angelova 4:44 PN11512582Lukas Kovalik M 5.16 PNcurl --location "httns:ani.hubani.com/crm/v3/obiects/contacts/search--header 'Content-vne' annlication/ison'--header "Authorization: BearerC|Kvma?iMx7OINOM8kOFwrAowAcAkUAhIR24?A05D?xiVrIYMILuP6SA01Kwcmhr=n.v2 hytorDniMvDalYck-CMalovolNOM9kOFwrAUAcrkcaws-ThwRARIRAOF-ATFSAOFRAO-ROIEBAQUBEggBAQEBAYICFIr7Au8O2Nwal9YW2CbCCxYvwngmSgNldTFSAFoAYABoAHAAeAA'\--data "{ "limit", 13'Message Aneliva Angelova+ AaIAl Notes: OffLeavev Q SearchDate ModifiedYesterdav at 13.33Yesterday at 13:33Yesterday at 13.32Yesterdav at 13:31Yesterday at 13:30Yesterdav at 13:30Yesterday at 13:29Yesterday at 13.28Yesterdav at 13:28resterday at 15.21Yesterdav at 13:26Yesterday at 13:26Yesterday at 13:2:Yesterday at 13:23Yesterdav at 13:24resterday at 13-43Yesterdav at 13:22Yesterday at 13:20Voctordau at 12:20lYesterday at 13.19Yesterdav at 13:18Yesterdav at 13:18Yesterday at 13:17Yesterday at 13:17Yesterday at 13:16Yesterday at 13.15Yecterdav at 12:15Yesterdav at 13:14Yesterday at 13-14Yesterdav at 13:13Yesterday at 13:13Yesterday at 13:12Yecterdav at 12:11Yesterday at 13:10Yesterdav at 13:10Yesterday at 13:09Yesterday at 13:08Yoctorday at 12:09Yesterday at 13.0/Yocterdav at 13:06Yesterday at 13:06Yesterdav at 13:05MPEG-4 movie12 KB9 KBMDEG-A movieMPEG-4 movieMPEG-4 movie8 KE37 KB10 KBMPEG-4 movie7 K:8 KBMDEG-A movie9 KBMPEG-4 movie72 KB14 KB15 Kb9 K:MPEG-4 movieMPEG-4 movie18 KBMDECA mavio12 KE10 K:MPEG-4 movie16 KRI6 KBMPEG-A movidMPEG-4 movie12 KE23 KB8 KBMPEG-4 movie6 KB1MPEG-4 movieMDSGLA movic11 KB11 KBMPEG-4 movie20 KE34 KBMPEG-4 movieMPEG-4 movie10 KB7K:MPEG-4 movieMDEG.A movid11 KB26 KBMPEG-4 movie111 KPMDEG-A movie102 KBMPEG-4 movie88 KB59 K:98 KB97 KB66 KBMPEG-4 movieMDEC.A moviaMPEG-4 movieЛAKE93 KB78 KBMDEG-A movieMPEG-4 movie50 K:MPEG-A movid58 KB MPEG-4 movie27 KB7 KB112 KрMPEG-4 movieMDSG.A movio32 KB17 KBMPEG-4 movie19 Kг32 KBMDECA movid10 KB24 K8MPEG-4 movieFavourites• jiminny• Recents* ApplicationsiCloud• iCloud Drive992 Svnc tolde0 DXP4800PLUS-B5F49 Networl• CRMI• Orange• Red|• Yellow• Green• Purple•) All lags..IhlDownloadsNameLoom.pkgAlfred copv.alfredoreterences=KeychronAssist-1.0.2 (1).dmeKeychronAssist-1.0.2.dmgmazanoke-images-yWJo.zioPhotos-3-001.zip• Transcript.pd→mage U.loge1 Orioninstaller.dma- image (2).1pc• ПO-22221726037035-004-001_ORGES.pdf%D0%9F%D0%9E-22221726037035-004-001 archive.zipПO-22221726037035-004-001_archive (1).zip• repon 4).XmAltred copy2.altredoreterencesСE 060209С О000000026571172 CWICT 0Р70501260015900 ndt= 27022026_0000000026574472_ SWIFT_ [IBAN].pdf= 03042026 [CREDIT_CARD] SWIFT [CREDIT_CARD].001reportxmmi=pdt.odiB pdf-1.pdfD pdf-2.pdf-pdf-5.pd1= ndf-1 ndipdf-3.pdfP Kdf-a,k Ffmiv Tree.sebitwarden export 20251031122528.isonlKoválik Family Tree.zip*macOS Storage_Cleanup.mdal favicon icofirst aid_notes_complete.docxrenortl2).esviconfig.vmlIteration run Search HS.postman_collection.json--report(1).csvm licence hettertouchtoalMariusHosting Config.isonnokc.901a6502.6667.A62h-062 ccu•Alfredv P1 mazanoko imaaoc. VWI6ана Ковалик.jpg•искане даниел Ковалик..pg• Фактура Март Даниел Ковалик.jрс• Фактура Април Даниел Ковалик iро• Dhotac 2.001Q SearchKind00,4 MD55.9 MBinstdlle..dckageAlfred...ferences10,1 MB10,1 MBIL MBDisk ImageDisk ImageLiP archive6.6 MBZIp archive2,5 MB PDF Document2,5 MBJreo lmage2.2 MBDisk Image2,2 MB PDF Document2 MBJPEG image1,9 MBJPEG imaqe192 KBPDE Document140 KbZIP archive148 KВ148 KB122 KBZIP archivelZIP archiveXML document111 KBAlfred...ferences94 KBDDE Documont92 KBPDr DocumentK:PDF Document91 KB91 KBXML document30 KBn0kpDDE Nocumont28 KBPDF Document28 KRPDE Document28 KB27 KBDocument14 KB11 KB6 KB6KBJSONINCV NacumontZIP archiveMarkdo…..ument5KRWindo...n image4 KB3 KBword ..cumentCSV Document2 KBVAMI dosumon1 KB029 buteccSV Documenthttlicence183 bytesZero butesJSONAlfrod foronso!Zero bytesFolde1.9 MB1,8 MB17 MB1,7 MBColdorJPEG imageJPEG ImageIPEG imadeJPEG imageColdo1 of 58 selected, 9.65 GB availabld• Inu 14 May 1/.20:04Date AddedIs Mdl ZUzo dl 19:4530 Jan 2026 at 12:3617 Mar 2026 at 20:2717 Mar 2026 at 20:26Z3 Aor 2020 al 13:0229 ,Jan 2026 at 15:2019 Dec 2025 at 10:1619 Dec 2025 at 12:238 Aor 2026 at 20:3519 Dec 2025 at 10:2919 Dec 2025 at 12:1819 Dec 2025 at 12:4026 Mar 2026 at 11:2410 May 2026 at 13:5326 Mar 2026 at 11:2426 Mar 2026 at 11:2426 Mar 2026 at 11:2310 May 2026 at 14:3730 Jan 2026 at 12:3712 Goh 2006 9t 11:5 A1Z3 Apr 2026 at 13.0823 Aor 2026 at 13:0810 May 2026 at 13:5410 May 2026 at 14:3710 May 2026 at 13:4910 May 2026 at 13:5010 May 2026 at 13:5110 Mav 2026 at 12:51110 May 2026 at 13:5019 Dec 2025 at 11:3431 Oct 2025 at 12:2525 Nau 2025 4+ 17:506 Mar 2026 at 11.2224 Anr 2026 at 16:5220 Oct 2025 at 11:0218 Mar 2026 at 15:29• Mav 2026 at 11:09129 Oct 2025 at 19:329 May 2026 at 10:0419 Mar 2026 at 11:55|10 May 2026 at 13:5712 Jun 2025 at 19:0430 Jan 2026 at 12:362616 Oct 2025 aт 16:0122 Aar 2026 at 12:0223 Apr 2026 at 13:0223 Apr 2026 at 13:0222 Anr 2026 at 12:0223 Apr 2026 at 13:0229 Jan 2026 at 15:20...
|
45115
|
NULL
|
NULL
|
NULL
|
|
45118
|
1619
|
66
|
2026-05-14T14:20:03.950365+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768403950_m1.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.054166667,"top":0.027777778,"width":0.08055556,"height":0.035555556},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.13472222,"top":0.027777778,"width":0.25555557,"height":0.035555556},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.6326389,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.6645833,"top":0.027777778,"width":0.15902779,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.82361114,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.8472222,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.87083334,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.9291667,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9527778,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9763889,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.64166665,"top":0.34666666,"width":0.015277778,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.66041666,"top":0.34444445,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.67569447,"top":0.34444445,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.69375,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.7118056,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.7347222,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.75277776,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.7708333,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.79375,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.81666666,"top":0.20666666,"width":0.050694443,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.87222224,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.9138889,"top":0.20666666,"width":0.059027776,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"bounds":{"left":0.8645833,"top":0.24111111,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.8854167,"top":0.24111111,"width":0.015277778,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.9048611,"top":0.24111111,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"4","depth":4,"bounds":{"left":0.92569447,"top":0.24111111,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.9458333,"top":0.23888889,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.9611111,"top":0.23888889,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","depth":4,"on_screen":true,"value":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.025,"top":0.06666667,"width":0.050694443,"height":0.034444444},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2936739681513006038
|
4956946545843311197
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45117
|
1619
|
65
|
2026-05-14T14:20:02.394830+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768402394_m1.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest v8• Thu 14 May 17:20:02* :QProject v© ReportController.php© AutomatedReportGenerated.php= custom.log= laravel.log› D Providers© TrackAutomatedReportGeneratedEvent.phpPlaybackController.phpD Sessionsv D Sms© UserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php> O IntercomSendReportJob.php• DeleteCrmEntityTrait.phpDeleteAccountJob.phpv D Planhat© ImportActivityTypes.php X© AccountController.php• IntegrationAppTrait.php=.env.staging18© CreateSmsRecei© CreateSmsSentEE.env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© CreateReceivedNotC SmsListener.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.php> D Softphone© HandleHubspotRateLimit.php© DialerMetricslmported.19class ImportActivitylypes implements ShouldQueueA1 ^© ElasticSearchMetricsR35public function handle(PlaybookCreated $event): void36© GenerateExportToken:© ImportRemote TrackLis37$playbook = $event->playbook;© PlanhatActivityListene38ReindexForAccountLis39// Don't run if somehow we already have categories.C ReindexForContactList40if ($playbook->getCategories()->isNotEmpty() {© ReindexForGroupListel41return;42C ReindexForLeadListen43ReindexForOpportunit!44© ReindexForUserListene$values = [];© ResolveProvider.php4546© SendExportEmail.phptry {© SetupintegrationActior47$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam(.22748© UserPilotActivityListen$crmService->syncField($playbook->getActivityField);> C Authentication49$values = $crmService->importPicklistValues($playbook->getActivityFi 22950v AutomatedReports} catch (Throwable $e) {v C UserPilot|51Log::warning( message:'[ImportActivityTypes] CRM API failed, falling 231© TrackAutomatedRe52'playbook_id' = $playbook->getid,Calendars53'team_id' => $playbook->getTeamId(),D Crm54'error' => $e->getMessage,55BootstrapintegrationAl1):© ImportActivityTypes.pl56© ImportMetadata.php57© InitProfiles.php58if (empty($values)) {@ I avnitMndifierl istene59$values = $this->fetchActivityFieldValues($playbook->getActivityFieliWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)4 SF (jiminny@localhost]HS_local (jiminny@localhost)4 console [QAI PROD] X« console [PROD]« console [EU]D m teams;223224225226228230232233 /234Tx: Auto vd8 jiminny v08 41 A3 44 A Vm migrations order by id desc;m teams where id IN (1, 1037);m crm_layouts where crm_configuration_id = 1M crm_layout_entities WHERE crm_layout_id =M crm_fields WHERE id IN (1652,1661,66799,66m features;m team_features where feature_id = 33;m opportunities;1.id, CASE WHEN u.id = t.owner_id THEN • (ownid FROM social_accounts saon u.id = sa.sociable_id1..n<->1: on t.id = u.team_idLid = 1052 and sa.provider = 'hubspot':accounts where id = 11512582;activities where account_id = 11512582;W Windsurf Teams48:30UTF-8Co 4 spaces...
|
NULL
|
-2427521127651226964
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormFileEditViewNavigateCodeLaravelRefactorRun PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest v8• Thu 14 May 17:20:02* :QProject v© ReportController.php© AutomatedReportGenerated.php= custom.log= laravel.log› D Providers© TrackAutomatedReportGeneratedEvent.phpPlaybackController.phpD Sessionsv D Sms© UserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php> O IntercomSendReportJob.php• DeleteCrmEntityTrait.phpDeleteAccountJob.phpv D Planhat© ImportActivityTypes.php X© AccountController.php• IntegrationAppTrait.php=.env.staging18© CreateSmsRecei© CreateSmsSentEE.env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© CreateReceivedNotC SmsListener.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.php> D Softphone© HandleHubspotRateLimit.php© DialerMetricslmported.19class ImportActivitylypes implements ShouldQueueA1 ^© ElasticSearchMetricsR35public function handle(PlaybookCreated $event): void36© GenerateExportToken:© ImportRemote TrackLis37$playbook = $event->playbook;© PlanhatActivityListene38ReindexForAccountLis39// Don't run if somehow we already have categories.C ReindexForContactList40if ($playbook->getCategories()->isNotEmpty() {© ReindexForGroupListel41return;42C ReindexForLeadListen43ReindexForOpportunit!44© ReindexForUserListene$values = [];© ResolveProvider.php4546© SendExportEmail.phptry {© SetupintegrationActior47$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam(.22748© UserPilotActivityListen$crmService->syncField($playbook->getActivityField);> C Authentication49$values = $crmService->importPicklistValues($playbook->getActivityFi 22950v AutomatedReports} catch (Throwable $e) {v C UserPilot|51Log::warning( message:'[ImportActivityTypes] CRM API failed, falling 231© TrackAutomatedRe52'playbook_id' = $playbook->getid,Calendars53'team_id' => $playbook->getTeamId(),D Crm54'error' => $e->getMessage,55BootstrapintegrationAl1):© ImportActivityTypes.pl56© ImportMetadata.php57© InitProfiles.php58if (empty($values)) {@ I avnitMndifierl istene59$values = $this->fetchActivityFieldValues($playbook->getActivityFieliWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)4 SF (jiminny@localhost]HS_local (jiminny@localhost)4 console [QAI PROD] X« console [PROD]« console [EU]D m teams;223224225226228230232233 /234Tx: Auto vd8 jiminny v08 41 A3 44 A Vm migrations order by id desc;m teams where id IN (1, 1037);m crm_layouts where crm_configuration_id = 1M crm_layout_entities WHERE crm_layout_id =M crm_fields WHERE id IN (1652,1661,66799,66m features;m team_features where feature_id = 33;m opportunities;1.id, CASE WHEN u.id = t.owner_id THEN • (ownid FROM social_accounts saon u.id = sa.sociable_id1..n<->1: on t.id = u.team_idLid = 1052 and sa.provider = 'hubspot':accounts where id = 11512582;activities where account_id = 11512582;W Windsurf Teams48:30UTF-8Co 4 spaces...
|
45116
|
NULL
|
NULL
|
NULL
|
|
45116
|
1619
|
64
|
2026-05-14T14:20:00.897681+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768400897_m1.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.054166667,"top":0.027777778,"width":0.08055556,"height":0.035555556},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.13472222,"top":0.027777778,"width":0.25555557,"height":0.035555556},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.6326389,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.6645833,"top":0.027777778,"width":0.15902779,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.82361114,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.8472222,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.87083334,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.9291667,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9527778,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9763889,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.64166665,"top":0.34666666,"width":0.015277778,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.66041666,"top":0.34444445,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.67569447,"top":0.34444445,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.69375,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.7118056,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.7347222,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.75277776,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.7708333,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.79375,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.81666666,"top":0.20666666,"width":0.050694443,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.87222224,"top":0.20666666,"width":0.018055556,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.9138889,"top":0.20666666,"width":0.059027776,"height":0.026666667},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"bounds":{"left":0.8645833,"top":0.24111111,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.8854167,"top":0.24111111,"width":0.015277778,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.9048611,"top":0.24111111,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"4","depth":4,"bounds":{"left":0.92569447,"top":0.24111111,"width":0.016666668,"height":0.02111111},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.9458333,"top":0.23888889,"width":0.015277778,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.9611111,"top":0.23888889,"width":0.014583333,"height":0.025555555},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","depth":4,"on_screen":true,"value":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.025,"top":0.06666667,"width":0.050694443,"height":0.034444444},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2936739681513006038
|
4956946545843311197
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45115
|
1620
|
44
|
2026-05-14T14:19:59.296471+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768399296_m2.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.2962101,"top":1.0,"width":0.03856383,"height":-0.019952059},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.33477393,"top":1.0,"width":0.122340426,"height":-0.019952059},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.5731383,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.5884308,"top":1.0,"width":0.076130316,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.66456115,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.67586434,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.6871675,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.7150931,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.72639626,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.73769945,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","depth":4,"bounds":{"left":0.39261967,"top":0.9074222,"width":0.2869016,"height":0.092577815},"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"4","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","depth":4,"on_screen":true,"value":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.28224733,"top":1.0,"width":0.024268618,"height":-0.04788506},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
2936739681513006038
|
4956946545843311197
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
45114
|
1619
|
63
|
2026-05-14T14:19:58.142671+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768398142_m1.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.054166667,"top":0.027777778,"width":0.08055556,"height":0.035555556},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.13472222,"top":0.027777778,"width":0.25555557,"height":0.035555556},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.6326389,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.6645833,"top":0.027777778,"width":0.15902779,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.82361114,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.8472222,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.87083334,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.9291667,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9527778,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9763889,"top":0.027777778,"width":0.023611112,"height":0.035555556},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6814957943380363182
|
-8708761519200826421
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
PhpStormFileEditViewNavigateCodeLaravelRefactorRunToolsGitWindowHelpabl100% C•FV faVsco.jsv* #12066 on JY-20725-handle-HS-search-rate-limit k vHandleHubspotRateLimitTest v8• Thu 14 May 17:19:57* :QProject v© ReportController.php© AutomatedReportGenerated.php= custom.log= laravel.log› D Providers© TrackAutomatedReportGeneratedEvent.phpPlaybackController.phpD Sessionsv D Sms© UserAutomatedReportsController.phpPlanhatService.phpAutomatedReportResult.php> O IntercomSendReportJob.php• DeleteCrmEntityTrait.phpDeleteAccountJob.phpv D Planhat© ImportActivityTypes.php X© AccountController.php• IntegrationAppTrait.php= .env.staging18© CreateSmsRecei© CreateSmsSentEE.env© DetachActivityObject.phpRematchActivityOnCrmObjectDetach.php© CreateReceivedNotC SmsListener.php© MatchActivityCrmData.php© Client.php© HubspotPaginationService.php> D Softphone© HandleHubspotRateLimit.php© DialerMetricslmported.19class ImportActivitylypes implementsShouldQueueA1 ^© ElasticSearchMetricsR35public function handle(PlaybookCreated $event): void36© GenerateExportToken:© ImportRemote TrackLis37$playbook = $event->playbook;© PlanhatActivityListene38ReindexForAccountLis39// Don't run if somehow we already have categories.C ReindexForContactList40if ($playbook->getCategories()->isNotEmpty() {© ReindexForGroupListel41return;42C ReindexForLeadListen43ReindexForOpportunit!44© ReindexForUserListene$values = [];© ResolveProvider.php4546© SendExportEmail.phptry {© SetupintegrationActior47$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam(.227© UserPilotActivityListen48$crmService->syncField(Splaybook->getActivityField):> C Authentication49$values = $crmService->importPicklistValues($playbook->getActivityFi 22950v AutomatedReports} catch (Throwable $e) {v C UserPilot|51Log::warning( message:'[ImportActivityTypes] CRM API failed, falling 231© TrackAutomatedRe52'playbook_id' = $playbook->getid,Calendars53'team_id' => $playbook->getTeamId(),D Crm54'error' => $e->getMessage,55BootstrapintegrationAl1):© ImportActivityTypes.pl56© ImportMetadata.php57© InitProfiles.php58if (empty(Svalues)) {@ I avnitMndifierl istene59$values = $this->fetchActivityFieldValues($playbook->getActivityFieliWorkspace associated with branch 'JY-20725-handle-HS-search-rate-limit' has been restored // Rollback // Configure... (today 16:17)4 SF (jiminny@localhost]HS_local (jiminny@localhost)4 console [QAI PROD] X« console [PROD]« console [EU]D210211212213214215=216217218219220221222m teams;223224225226228230232233 /234Tx: Auto vd8 jiminny08 41 A3 44 A Vm migrations order by id desc;m teams where id IN (1, 1037);m crm_layouts where crm_configuration_id = 1M crm_layout_entities WHERE crm_layout_id =M crm_fields WHERE id IN (1652,1661,66799,66m features;m team_features where feature_id = 33;m opportunities;1.id, CASE WHEN u.id = t.owner_id THEN • (ownid FROM social_accounts sai on u.id = sa.sociable_id1..n<->1: on t.id = u.team_idLid = 1052 and sa.provider = 'hubspot':accounts where id = 11512582;activities where account_id = 11512582;W Windsurf Teams35:43 (15 chars)UTF-8Co 4 spaces...
|
45112
|
NULL
|
NULL
|
NULL
|
|
45113
|
1620
|
43
|
2026-05-14T14:19:58.180275+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-14/1778 /Users/lukas/.screenpipe/data/data/2026-05-14/1778768398180_m2.jpg...
|
PhpStorm
|
faVsco.js – ImportActivityTypes.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.2962101,"top":1.0,"width":0.03856383,"height":-0.019952059},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12066 on JY-20725-handle-HS-search-rate-limit, menu","depth":5,"bounds":{"left":0.33477393,"top":1.0,"width":0.122340426,"height":-0.019952059},"on_screen":true,"help_text":"Pull request #12066 exists for current branch JY-20725-handle-HS-search-rate-limit, but local branch is out of sync with remote","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.5731383,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"HandleHubspotRateLimitTest","depth":6,"bounds":{"left":0.5884308,"top":1.0,"width":0.076130316,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.66456115,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'HandleHubspotRateLimitTest'","depth":6,"bounds":{"left":0.67586434,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.6871675,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.7150931,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.72639626,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.73769945,"top":1.0,"width":0.011303191,"height":-0.019952059},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","depth":4,"bounds":{"left":0.39261967,"top":0.9074222,"width":0.2869016,"height":0.092577815},"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Listeners\\Crm;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Events\\Playbooks\\PlaybookCreated;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\FieldValue;\nuse Jiminny\\Models\\PlaybookCategory;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\PlaybookCategoryRepository;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\Log;\nuse Jiminny\\Services\\ResolveTeamCrmConnection;\nuse stdClass;\nuse Throwable;\n\nclass ImportActivityTypes implements ShouldQueue\n{\n /**\n * Create the event listener.\n */\n public function __construct(\n private readonly ResolveTeamCrmConnection $crmResolver,\n private readonly FieldRepository $fieldRepository,\n private readonly PlaybookCategoryRepository $repository,\n ) {\n // nothing\n }\n\n /**\n * Import the standard Event/Task Type picklist options from the CRM.\n */\n public function handle(PlaybookCreated $event): void\n {\n $playbook = $event->playbook;\n\n // Don't run if somehow we already have categories.\n if ($playbook->getCategories()->isNotEmpty()) {\n return;\n }\n\n $values = [];\n\n try {\n $crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());\n $crmService->syncField($playbook->getActivityField());\n $values = $crmService->importPicklistValues($playbook->getActivityField());\n } catch (Throwable $e) {\n Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'error' => $e->getMessage(),\n ]);\n }\n\n if (empty($values)) {\n $values = $this->fetchActivityFieldValues($playbook->getActivityField());\n\n Log::info('[ImportActivityTypes] Using database fallback for categories', [\n 'playbook_id' => $playbook->getId(),\n 'field_values_count' => $values->count(),\n ]);\n }\n\n $createdCount = 0;\n\n /** @var stdClass{label: string} $value */\n foreach ($values as $value) {\n $data = [\n 'name' => $value->label,\n 'enabled' => true,\n 'type' => PlaybookCategory::TYPE_ALL,\n ];\n\n if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;\n }\n\n if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {\n $data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;\n }\n\n $this->repository->create($playbook, $data);\n $createdCount++;\n }\n\n if ($createdCount === 0) {\n Log::warning('[ImportActivityTypes] No categories created for playbook', [\n 'playbook_id' => $playbook->getId(),\n 'team_id' => $playbook->getTeamId(),\n 'field_id' => $playbook->getActivityField()?->getId(),\n ]);\n }\n }\n\n private function fetchActivityFieldValues(Field $field): Collection\n {\n /** @var Collection<FieldValue> */\n return $this->fieldRepository->getPicklistValues($field);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"8","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"4","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","depth":4,"on_screen":true,"value":"SELECT\n# DISTINCT\nopp.id as opp_id, opp.uuid, opp.name,\n# COUNT(dr.id) AS deal_risk_count,\n\n# dr.id,\n# cfd.value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\n# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id\n# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id\n\nLEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 1\nAND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\nGROUP BY opp.id, cfd.value\nORDER BY\n# cfd.value\n CAST(cfd.value AS UNSIGNED)\n# owner_name\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1\n# AND gdrt.is_enabled = 1)\nDESC\nLIMIT 25\n# OFFSET 0\n;\n\nselect * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';\nselect * from crm_layout_entities where crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4584045;\nSELECT * FROM crm_field_data WHERE object_id = 4584045;\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'\n\nSELECT\n opp.id as opportunity_id,\n opp.name,\n COUNT(dr.id) as risk_count\nFROM opportunities opp\nLEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id\nWHERE opp.id IN (\n 6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788\n)\nGROUP BY opp.id;\n\nSELECT COUNT(dr.id)\n FROM deal_risks dr\n JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n WHERE dr.opportunity_id = 5563344\n# AND gdrt.group_id = usr.group_id\n\n\n\nEXPLAIN SELECT\n opp.id as opp_id, opp.uuid, opp.name,\n\ncfd.value,\ncfv.sequence,\ncfv.value,\n# MAX(cfd.value) AS max_cfd_value,\nusr.name AS owner_name,\nopp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,\nusr.uuid as owner_uuid,\nusr.photo_path as owner_photo,\nusr.id AS owner_id,\njt.name as owner_job,\nopp.stage_id, opp.stage_updated_at,\nacc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,\nrt.business_process_id AS pipeline_id\nFROM opportunities opp\n\nLEFT JOIN record_types rt ON opp.record_type_id = rt.id\nLEFT JOIN users usr ON opp.user_id = usr.id\nLEFT JOIN accounts acc ON opp.account_id = acc.id\nLEFT JOIN job_titles jt ON usr.job_title_id = jt.id\n\nLEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id\n FROM crm_field_data sub_cfd\n WHERE sub_cfd.object_id = opp.id\n AND sub_cfd.crm_field_id = 66810\n ORDER BY sub_cfd.updated_at DESC\n LIMIT 1)\n\nLEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value\n\nWHERE opp.user_id IS NOT NULL\nAND opp.deleted_at IS NULL\nAND opp.is_closed = 0\n# AND opp.is_closed = 1\n# AND opp.is_won = 0\nAND opp.close_date >= '2024-01-01 00:00:00'\nAND opp.close_date <= '2024-12-31 23:59:59'\nAND usr.team_id = 1\n\n# and opp.id = 4823179\n\n# GROUP BY opp.id\nORDER BY\n cfv.sequence DESC,\n# opp.name\n# owner_name\n cfd.value\n# CAST(cfd.value AS UNSIGNED)\n# CAST(MAX(cfd.value) AS UNSIGNED)\n# (SELECT COUNT(dr.id)\n# FROM deal_risks dr\n# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id\n# WHERE dr.opportunity_id = opp.id\n# AND dr.is_active = 1 AND gdrt.is_enabled = 1)\nDESC\n# LIMIT 75, 25\n;\n\n\n\nSELECT * FROM crm_field_values WHERE crm_field_id = 66810;\n\nSELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at\nFROM crm_fields f\nINNER JOIN crm_field_data fd ON fd.crm_field_id = f.id\n WHERE (f.crm_configuration_id = 1)\n AND (f.object_type = 'opportunity')\n# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))\n AND (fd.object_id IN (4158460))\n AND (f.crm_provider_id IN ('ForecastCategoryName'))\n ORDER BY fd.object_id ASC, fd.updated_at DESC;\n\nselect * from crm_layouts where crm_configuration_id = 1;\nselect cf.* from crm_fields cf\njoin crm_layout_entities cle on cf.id = cle.crm_field_id\nwhere crm_layout_id = 1493;\n\nSELECT * FROM opportunities WHERE id = 4158460;\nSELECT * FROM crm_field_data WHERE object_id = 4158460;\n\nselect * from users where team_id = 1;\nSELECT * FROM users WHERE id = 7160;\nselect * from role_user where user_id = 3248;\n\nselect * from crm_field_values where crm_field_id = 66824;\n\nSELECT * FROM users WHERE id = 23470;\nselect * from crm_configurations;\n\n# ******************************************\nselect * from teams where id = 1038; # 23521, 966\nselect * from users where team_id = 1038;\nselect * from crm_configurations where id = 966;\nSELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762\nSELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764\nSELECT * FROM participants WHERE activity_id = 54965764;\n\nSELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075\nSELECT * FROM participants WHERE activity_id = 54964075;\nselect f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id\n where tf.team_id = 1038;\n\n\n# ****************************************** PD *************************\nselect * from teams where id = 1029;\nSELECT * FROM crm_configurations WHERE id = 957;\nSELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421\n\n# ****************************************** Close *************************\nselect * from teams where id = 1031;\nSELECT * FROM crm_configurations WHERE id = 959;\nSELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517\n\n\nSELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433\n\nSELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009\n\n# ****************************************** SF *************************\nSELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;\n\nselect * from roles;\nselect * from permissions;\nselect * from permission_role where permission_id = 136;\n\nselect * from migrations order by id desc;\n\nselect * from teams where id IN (1, 1037);\nselect * from crm_layouts where crm_configuration_id = 1;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;\nSELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);\n\nselect * from features;\nselect * from team_features where feature_id = 33;\nselect * from opportunities;\n\nselect * from teams;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1052 and sa.provider = 'hubspot';\n\nSELECT * FROM accounts where id = 11512582;\nselect * from activities where account_id = 11512582;","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.28224733,"top":1.0,"width":0.024268618,"height":-0.04788506},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-3070454358504145234
|
4956946545977528925
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
#12066 on JY-20725-handle Project: faVsco.js, menu
#12066 on JY-20725-handle-HS-search-rate-limit, menu
Start Listening for PHP Debug Connections
HandleHubspotRateLimitTest
Run 'HandleHubspotRateLimitTest'
Debug 'HandleHubspotRateLimitTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Listeners\Crm;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Jiminny\Events\Playbooks\PlaybookCreated;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldValue;
use Jiminny\Models\PlaybookCategory;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\PlaybookCategoryRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
use Jiminny\Services\ResolveTeamCrmConnection;
use stdClass;
use Throwable;
class ImportActivityTypes implements ShouldQueue
{
/**
* Create the event listener.
*/
public function __construct(
private readonly ResolveTeamCrmConnection $crmResolver,
private readonly FieldRepository $fieldRepository,
private readonly PlaybookCategoryRepository $repository,
) {
// nothing
}
/**
* Import the standard Event/Task Type picklist options from the CRM.
*/
public function handle(PlaybookCreated $event): void
{
$playbook = $event->playbook;
// Don't run if somehow we already have categories.
if ($playbook->getCategories()->isNotEmpty()) {
return;
}
$values = [];
try {
$crmService = $this->crmResolver->resolveForTeam($playbook->getTeam());
$crmService->syncField($playbook->getActivityField());
$values = $crmService->importPicklistValues($playbook->getActivityField());
} catch (Throwable $e) {
Log::warning('[ImportActivityTypes] CRM API failed, falling back to database values', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'error' => $e->getMessage(),
]);
}
if (empty($values)) {
$values = $this->fetchActivityFieldValues($playbook->getActivityField());
Log::info('[ImportActivityTypes] Using database fallback for categories', [
'playbook_id' => $playbook->getId(),
'field_values_count' => $values->count(),
]);
}
$createdCount = 0;
/** @var stdClass{label: string} $value */
foreach ($values as $value) {
$data = [
'name' => $value->label,
'enabled' => true,
'type' => PlaybookCategory::TYPE_ALL,
];
if (Str::contains(strtolower($value->label), ['sms sent', 'sms out', 'text in'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_OUTBOUND;
}
if (Str::contains(strtolower($value->label), ['sms received', 'sms in', 'text out'])) {
$data['type'] = PlaybookCategory::TYPE_SMS_INBOUND;
}
$this->repository->create($playbook, $data);
$createdCount++;
}
if ($createdCount === 0) {
Log::warning('[ImportActivityTypes] No categories created for playbook', [
'playbook_id' => $playbook->getId(),
'team_id' => $playbook->getTeamId(),
'field_id' => $playbook->getActivityField()?->getId(),
]);
}
}
private function fetchActivityFieldValues(Field $field): Collection
{
/** @var Collection<FieldValue> */
return $this->fieldRepository->getPicklistValues($field);
}
}
Execute
Explain Plan
Browse Query History
View Parameters
Open Query Execution Settings…
In-Editor Results
Tx: Auto
Cancel Running Statements
Playground
jiminny
Sync Changes
Hide This Notification
Code changed:
Hide
8
1
3
4
Previous Highlighted Error
Next Highlighted Error
SELECT
# DISTINCT
opp.id as opp_id, opp.uuid, opp.name,
# COUNT(dr.id) AS deal_risk_count,
# dr.id,
# cfd.value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
# LEFT JOIN group_deal_risk_types gdrt ON gdrt.group_id = usr.group_id
# LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id AND dr.group_deal_risk_type_id = gdrt.id
LEFT JOIN crm_field_data cfd ON (cfd.object_id = opp.id and cfd.crm_field_id = 66814)
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 1
AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
GROUP BY opp.id, cfd.value
ORDER BY
# cfd.value
CAST(cfd.value AS UNSIGNED)
# owner_name
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1
# AND gdrt.is_enabled = 1)
DESC
LIMIT 25
# OFFSET 0
;
select * from crm_fields where crm_configuration_id = 1 and object_type = 'opportunity';
select * from crm_layout_entities where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4584045;
SELECT * FROM crm_field_data WHERE object_id = 4584045;
SELECT * FROM opportunities where team_id = 1 and crm_provider_id = '0061K00000lfb9IQAQ'
SELECT
opp.id as opportunity_id,
opp.name,
COUNT(dr.id) as risk_count
FROM opportunities opp
LEFT JOIN deal_risks dr ON dr.opportunity_id = opp.id
WHERE opp.id IN (
6069574,8900938,9507638,9524799,9660490,9662824,9705675,9749758,4158460,4391812,6450439,4448422,5118945,5590675,4584045,7228149,9002408,9165534,9446720,9641778,9665149,9703344,9709280,5747948,4158491,6182565,6263970,5798120,5111315,4536978,6062352,6548383,6072095,6548225,4480986,5011422,6548381,8760540,8917554,9509986,9514392,9569009,9569011,9578490,9713604,5784397,7276612,7288405,8994421,9118219,9608148,9818911,4510535,6479693,5958049,6271674,6550448,4158331,4158483,6126571,6171615,6540943,4897466,5190896,5796182,5932762,8572433,8723698,8892697,9711001,9789264,4549188,6100831,6170064,6260799,6263653,6449936,6530871,6538978,7777651,8059269,8319918,8787049,8901150,9263153,9453207,9514738,9696700,9791062,5752018,6421452,7439134,7878923,9354763,9369285,9514396,9582506,9889949,9890216,4094311,4158495,4158496,6098128,5585661,3872564,6442149,5891604,6164746,6199593,6583474,6519684,9018490,9809006,4496897,5041324,5829430,6198319,6253504,6555763,7242914,7931055,8024125,8797814,8058559,8673347,8892695,8994420,9616219,9714970,9722004,9809439,9818918,6523177,8134147,9002915,9711422,9892713,9901719,9954210,9978435,5800810,6243518,6416114,6222251,6411974,6512456,5791953,6545606,9914780,5805540,6238986,6463838,6547680,9767049,9809437,9810885,9890855,6673493,9902036,4335521,6379871,6503799,6546077,8018765,9907556,9958433,9905855,9916179,9946741,9957877,5563344,6271838,6450815,7641128,7762567,7780592,8684810,8685786,8685787,8685788
)
GROUP BY opp.id;
SELECT COUNT(dr.id)
FROM deal_risks dr
JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
WHERE dr.opportunity_id = 5563344
# AND gdrt.group_id = usr.group_id
EXPLAIN SELECT
opp.id as opp_id, opp.uuid, opp.name,
cfd.value,
cfv.sequence,
cfv.value,
# MAX(cfd.value) AS max_cfd_value,
usr.name AS owner_name,
opp.value, opp.currency_code, opp.close_date, opp.remotely_created_at, opp.is_closed, opp.is_won,
usr.uuid as owner_uuid,
usr.photo_path as owner_photo,
usr.id AS owner_id,
jt.name as owner_job,
opp.stage_id, opp.stage_updated_at,
acc.name AS acc_name, opp.stage_updated_at, acc.crm_provider_id AS acc_provider_id, opp.crm_provider_id AS opp_provider_id,
rt.business_process_id AS pipeline_id
FROM opportunities opp
LEFT JOIN record_types rt ON opp.record_type_id = rt.id
LEFT JOIN users usr ON opp.user_id = usr.id
LEFT JOIN accounts acc ON opp.account_id = acc.id
LEFT JOIN job_titles jt ON usr.job_title_id = jt.id
LEFT JOIN crm_field_data cfd ON cfd.id = (SELECT sub_cfd.id
FROM crm_field_data sub_cfd
WHERE sub_cfd.object_id = opp.id
AND sub_cfd.crm_field_id = 66810
ORDER BY sub_cfd.updated_at DESC
LIMIT 1)
LEFT JOIN crm_field_values cfv ON cfv.crm_field_id = 66810 AND cfv.value = cfd.value
WHERE opp.user_id IS NOT NULL
AND opp.deleted_at IS NULL
AND opp.is_closed = 0
# AND opp.is_closed = 1
# AND opp.is_won = 0
AND opp.close_date >= '2024-01-01 00:00:00'
AND opp.close_date <= '2024-12-31 23:59:59'
AND usr.team_id = 1
# and opp.id = 4823179
# GROUP BY opp.id
ORDER BY
cfv.sequence DESC,
# opp.name
# owner_name
cfd.value
# CAST(cfd.value AS UNSIGNED)
# CAST(MAX(cfd.value) AS UNSIGNED)
# (SELECT COUNT(dr.id)
# FROM deal_risks dr
# JOIN group_deal_risk_types gdrt ON dr.group_deal_risk_type_id = gdrt.id
# WHERE dr.opportunity_id = opp.id
# AND dr.is_active = 1 AND gdrt.is_enabled = 1)
DESC
# LIMIT 75, 25
;
SELECT * FROM crm_field_values WHERE crm_field_id = 66810;
SELECT f.id, f.crm_provider_id AS field_name, f.label, fd.object_id AS dealId, fd.value, fd.updated_at, fd.id, fd.created_at
FROM crm_fields f
INNER JOIN crm_field_data fd ON fd.crm_field_id = f.id
WHERE (f.crm_configuration_id = 1)
AND (f.object_type = 'opportunity')
# AND (fd.object_id IN (4158331,4158483,4158495,4158496,6069574,6263970,6171615,6540943,6545606,5829430,6198319,6263653,6548381,7242914,8797814,7228149,7439134,7878923,8134147,9002915,9118219,9165534,9354763,9369285,9446720))
AND (fd.object_id IN (4158460))
AND (f.crm_provider_id IN ('ForecastCategoryName'))
ORDER BY fd.object_id ASC, fd.updated_at DESC;
select * from crm_layouts where crm_configuration_id = 1;
select cf.* from crm_fields cf
join crm_layout_entities cle on cf.id = cle.crm_field_id
where crm_layout_id = 1493;
SELECT * FROM opportunities WHERE id = 4158460;
SELECT * FROM crm_field_data WHERE object_id = 4158460;
select * from users where team_id = 1;
SELECT * FROM users WHERE id = 7160;
select * from role_user where user_id = 3248;
select * from crm_field_values where crm_field_id = 66824;
SELECT * FROM users WHERE id = 23470;
select * from crm_configurations;
# [PASSWORD_DOTS]
select * from teams where id = 1038; # 23521, 966
select * from users where team_id = 1038;
select * from crm_configurations where id = 966;
SELECT * FROM activities WHERE uuid_to_bin('e8dc7c34-31f6-4430-bd81-2d9d8f00dd07') = uuid; # 54965762
SELECT * FROM activities WHERE uuid_to_bin('4b5727c0-69d1-428f-b8d9-b649055166e2') = uuid; # 54965764
SELECT * FROM participants WHERE activity_id = 54965764;
SELECT id, uuid, title, recording_state FROM activities WHERE uuid_to_bin('355f105d-5606-4379-b0c5-d91daf59f4ce') = uuid; # 54964075
SELECT * FROM participants WHERE activity_id = 54964075;
select f.id, slug, title, tf.team_id from team_features tf JOIN features f on tf.feature_id = f.id
where tf.team_id = 1038;
# [PASSWORD_DOTS] PD [PASSWORD_DOTS]
select * from teams where id = 1029;
SELECT * FROM crm_configurations WHERE id = 957;
SELECT * FROM activities WHERE uuid_to_bin('581a33cb-4343-44bd-ac0c-4a5cee71c5ec') = uuid; # 54963423
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('8b6bb2f7-e7a7-4aec-8806-fbfea7093ccd') = uuid; # 54963421
# [PASSWORD_DOTS] Close [PASSWORD_DOTS]
select * from teams where id = 1031;
SELECT * FROM crm_configurations WHERE id = 959;
SELECT * FROM activities WHERE uuid_to_bin('59c517e0-96c9-4dad-bfeb-b7bef72f8725') = uuid; # 54963517
SELECT * FROM activities WHERE uuid_to_bin('07238011-25fa-418e-838b-fb21e82b9ea2') = uuid; # 54963433
SELECT * FROM activities WHERE uuid_to_bin('d68311e3-ac34-49bd-bf04-88323a7e5352') = uuid; # 54966009
# [PASSWORD_DOTS] SF [PASSWORD_DOTS]
SELECT * FROM activities WHERE uuid_to_bin('2bd4cfa3-4eb5-4c77-84a7-9ed46a21c988') = uuid;
select * from roles;
select * from permissions;
select * from permission_role where permission_id = 136;
select * from migrations order by id desc;
select * from teams where id IN (1, 1037);
select * from crm_layouts where crm_configuration_id = 1;
SELECT * FROM crm_layout_entities WHERE crm_layout_id = 1493;
SELECT * FROM crm_fields WHERE id IN (1652,1661,66799,66814,66821,66836,66843,66846,66864,84752,182306,323580,380378);
select * from features;
select * from team_features where feature_id = 33;
select * from opportunities;
select * from teams;
SELECT
CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,
u.email,
sa.*,
t.owner_id FROM social_accounts sa
JOIN users u on u.id = sa.sociable_id
JOIN teams t on t.id = u.team_id
WHERE u.team_id = 1052 and sa.provider = 'hubspot';
SELECT * FROM accounts where id = 11512582;
select * from activities where account_id = 11512582;
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options...
|
45110
|
NULL
|
NULL
|
NULL
|